[tizenipc] Change zero copy buffer handling 95/188895/11
authorJeongmo Yang <jm80.yang@samsung.com>
Tue, 11 Sep 2018 10:55:24 +0000 (19:55 +0900)
committerJeongmo Yang <jm80.yang@samsung.com>
Mon, 1 Oct 2018 08:38:52 +0000 (08:38 +0000)
[Version] 1.0.0-60
[Profile] Common
[Issue Type] Update
[Dependency module] N/A

Change-Id: Ia58644a4d9ca0b34157a93841e1b90e4b98fd263
Signed-off-by: Jeongmo Yang <jm80.yang@samsung.com>
Makefile.am [changed mode: 0755->0644]
configure.ac
packaging/gst-plugins-tizen.spec
tizenipc/src/Makefile.am
tizenipc/src/gsttizenipc.h [new file with mode: 0644]
tizenipc/src/gsttizenipcsink.c
tizenipc/src/gsttizenipcsink.h
tizenipc/src/gsttizenipcsrc.c
tizenipc/src/gsttizenipcsrc.h

old mode 100755 (executable)
new mode 100644 (file)
index fee158f..021fc8f 100644 (file)
@@ -156,8 +156,6 @@ AC_SUBST(GST_VIDEO_CFLAGS)
 AC_SUBST(GST_VIDEO_LIBS)
 
 PKG_CHECK_MODULES(GST_ALLOCATORS, gstreamer-allocators-$GST_MAJORMINOR >= $GST_REQUIRED)
-
-dnl make _CFLAGS and _LIBS available
 AC_SUBST(GST_ALLOCATORS_CFLAGS)
 AC_SUBST(GST_ALLOCATORS_LIBS)
 
@@ -177,10 +175,6 @@ PKG_CHECK_MODULES(MMCOMMON,mm-common)
 AC_SUBST(MMCOMMON_CFLAGS)
 AC_SUBST(MMCOMMON_LIBS)
 
-PKG_CHECK_MODULES([GST_ALLOCATORS], [gstreamer-allocators-1.0])
-AC_SUBST(GST_ALLOCATORS_CFLAGS)
-AC_SUBST(GST_ALLOCATORS_LIBS)
-
 dnl belows are related to wfdtsdemux
 AG_GST_ARG_WITH_PACKAGE_NAME
 AG_GST_ARG_WITH_PACKAGE_ORIGIN
index cbe1603..8349f9f 100644 (file)
@@ -9,7 +9,7 @@
 Name:       gst-plugins-tizen
 Version:    1.0.0
 Summary:    GStreamer tizen plugins (common)
-Release:    59
+Release:    60
 Group:      Multimedia/Framework
 Url:        http://gstreamer.freedesktop.org/
 License:    LGPL-2.1+
@@ -18,6 +18,7 @@ Source0:    %{name}-%{version}.tar.gz
 BuildRequires:  pkgconfig(gstreamer-audio-1.0)
 BuildRequires:  pkgconfig(gstreamer-video-1.0)
 BuildRequires:  pkgconfig(gstreamer-plugins-base-1.0)
+BuildRequires:  pkgconfig(gstreamer-allocators-1.0)
 BuildRequires:  pkgconfig(gstreamer-1.0)
 BuildRequires:  pkgconfig(libexif)
 %if %{with x}
index c0bbd25..bc88145 100644 (file)
@@ -18,8 +18,8 @@ libgsttizenipcsink_la_SOURCES = gsttizenipcsink.c
 
 # flags used to compile this plugin
 # add other _CFLAGS and _LIBS as needed
-libgsttizenipcsink_la_CFLAGS = $(GST_CFLAGS) $(GST_PLUGINS_BASE_CFLAGS) $(GST_BASE_CFLAGS) $(TBM_CFLAGS) $(MMCOMMON_CFLAGS)
-libgsttizenipcsink_la_LIBADD = $(GST_LIBS) $(GST_PLUGINS_BASE_LIBS) $(GST_BASE_LIBS) $(TBM_LIBS)
+libgsttizenipcsink_la_CFLAGS = $(GST_CFLAGS) $(GST_PLUGINS_BASE_CFLAGS) $(GST_BASE_CFLAGS) $(GST_ALLOCATORS_CFLAGS) $(TBM_CFLAGS)
+libgsttizenipcsink_la_LIBADD = $(GST_LIBS) $(GST_PLUGINS_BASE_LIBS) $(GST_BASE_LIBS) $(GST_ALLOCATORS_LIBS) $(TBM_LIBS)
 libgsttizenipcsink_la_LDFLAGS = $(GST_PLUGIN_LDFLAGS)
 
 # sources used to compile this plug-in
@@ -27,8 +27,8 @@ libgsttizenipcsrc_la_SOURCES = gsttizenipcsrc.c
 
 # flags used to compile this plugin
 # add other _CFLAGS and _LIBS as needed
-libgsttizenipcsrc_la_CFLAGS = $(GST_CFLAGS) $(GST_PLUGINS_BASE_CFLAGS) $(GST_BASE_CFLAGS) $(TBM_CFLAGS) $(MMCOMMON_CFLAGS)
-libgsttizenipcsrc_la_LIBADD = $(GST_LIBS) $(GST_PLUGINS_BASE_LIBS) $(GST_BASE_LIBS) $(TBM_LIBS)
+libgsttizenipcsrc_la_CFLAGS = $(GST_CFLAGS) $(GST_PLUGINS_BASE_CFLAGS) $(GST_BASE_CFLAGS) $(GST_ALLOCATORS_CFLAGS) $(TBM_CFLAGS)
+libgsttizenipcsrc_la_LIBADD = $(GST_LIBS) $(GST_PLUGINS_BASE_LIBS) $(GST_BASE_LIBS) $(GST_ALLOCATORS_LIBS) $(TBM_LIBS)
 libgsttizenipcsrc_la_LDFLAGS = $(GST_PLUGIN_LDFLAGS)
 
 # headers we need but don't want installed
diff --git a/tizenipc/src/gsttizenipc.h b/tizenipc/src/gsttizenipc.h
new file mode 100644 (file)
index 0000000..1e56a18
--- /dev/null
@@ -0,0 +1,62 @@
+/*
+ * GStreamer Tizen IPC
+ *
+ * Copyright (C) 2018 Jeongmo Yang <jm80.yang@samsung.com>
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Library General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Library General Public License for more details.
+ *
+ * You should have received a copy of the GNU Library General Public
+ * License along with this library; if not, write to the Free
+ * Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+ * Boston, MA 02110-1301 USA.
+ */
+
+#ifndef __GST_TIZEN_IPC_H__
+#define __GST_TIZEN_IPC_H__
+
+#include <tbm_surface.h>
+
+G_BEGIN_DECLS
+
+#define IPC_BUFFER_MAX         30
+#define INIT_FD                (-1)
+
+typedef struct _GstTizenipcMessage GstTizenipcMessage;
+
+typedef enum {
+  TIZEN_IPC_SHM_PATH = 0,
+  TIZEN_IPC_SHM_SIZE,
+  TIZEN_IPC_BUFFER_TYPE,
+  TIZEN_IPC_BUFFER_CAPS,
+  TIZEN_IPC_BUFFER_NEW,
+  TIZEN_IPC_BUFFER_RECEIVED,
+  TIZEN_IPC_BUFFER_RELEASE,
+  TIZEN_IPC_CLOSE_CLIENT
+} TizenIPCID;
+
+typedef enum {
+  BUFFER_TYPE_NORMAL = 0,
+  BUFFER_TYPE_ZERO_COPY
+} BufferType;
+
+struct _GstTizenipcMessage {
+  TizenIPCID id;
+  union {
+    BufferType type;
+    int size;
+    int tbm_key[TBM_SURF_PLANE_MAX];
+  };
+};
+
+G_END_DECLS
+
+#endif /* __GST_TIZEN_IPC_H__ */
+
index 59de30e..3ec604d 100644 (file)
 #include <sys/socket.h>
 #include <sys/un.h>
 #include <fcntl.h>
+#include <gst/allocators/gsttizenmemory.h>
 #include "gsttizenipcsink.h"
 
 #define DEFAULT_SOCKET_PATH "/tmp/tizenipc.0"
-#define DEFAULT_SHM_PATH    "/tizenipcshm"
+#define DEFAULT_SHM_PATH    "/tmp/tizenipcshm"
 #define DEFAULT_PERMISSIONS (S_IRUSR|S_IWUSR|S_IRGRP)
 #define DEFAULT_BACKLOG     5
 #define CLIENT_RESPONSE_TIMEOUT_NORMAL      (G_TIME_SPAN_SECOND)
@@ -71,7 +72,8 @@ enum {
 };
 
 
-
+static gboolean __init_socket(GstTizenipcSink *self);
+static gboolean __init_shared_memory(GstTizenipcSink *self, guint shm_size);
 static gboolean _prepare_tizenipc_sink(GstTizenipcSink *self, guint shm_size);
 static gboolean _add_buffer_to_list(GstTizenipcSink *self, GstBuffer *buf, int *tbm_key);
 static gboolean _remove_buffer_from_list(GstTizenipcSink *self, int *tbm_key);
@@ -96,23 +98,19 @@ static guint signals[LAST_SIGNAL] = {0, 0};
 
 
 
-
-static gboolean _prepare_tizenipc_sink(GstTizenipcSink *self, guint shm_size)
+static gboolean __init_socket(GstTizenipcSink *self)
 {
   int i = 0;
   int flags = 0;
   struct sockaddr_un addr_un;
   struct sockaddr *address = NULL;
   socklen_t address_len = 0;
-  gchar shm_path[32] = {'\0',};
 
-  if (self == NULL) {
+  if (!self) {
     GST_ERROR("NULL handle");
     return FALSE;
   }
 
-  GST_INFO_OBJECT(self, "start - shared memory size %u", shm_size);
-
   /* open socket */
   self->socket_fd = socket(PF_UNIX, SOCK_STREAM, 0);
   if (self->socket_fd < 0) {
@@ -123,13 +121,13 @@ static gboolean _prepare_tizenipc_sink(GstTizenipcSink *self, guint shm_size)
   flags = fcntl(self->socket_fd, F_GETFL, NULL);
   if (flags < 0) {
     GST_ERROR_OBJECT(self, "failed to fcntl F_GETFL");
-    goto _FAILED;
+    goto _SOCKET_FAILED;
   }
 
   /* set non-block mode */
   if (fcntl (self->socket_fd, F_SETFL, flags|O_NONBLOCK) < 0) {
     GST_ERROR_OBJECT(self, "failed to fcntl F_SETFL");
-    goto _FAILED;
+    goto _SOCKET_FAILED;
   }
 
   memset(&addr_un, 0x0, sizeof(addr_un));
@@ -146,12 +144,12 @@ static gboolean _prepare_tizenipc_sink(GstTizenipcSink *self, guint shm_size)
   while (bind(self->socket_fd, address, address_len) < 0) {
     if (errno != EADDRINUSE) {
       GST_ERROR_OBJECT(self, "failed to bind. errno %d", errno);
-      goto _FAILED;
+      goto _SOCKET_FAILED;
     }
 
     if (i > 256) {
       GST_ERROR_OBJECT(self, "no more free socket name");
-      goto _FAILED;
+      goto _SOCKET_FAILED;
     }
 
     snprintf(addr_un.sun_path, sizeof(addr_un.sun_path), "%s.%d", self->socket_path, i);
@@ -168,21 +166,44 @@ static gboolean _prepare_tizenipc_sink(GstTizenipcSink *self, guint shm_size)
   self->socket_path_result = g_strdup(addr_un.sun_path);
   if (self->socket_path_result == NULL) {
     GST_ERROR_OBJECT(self, "failed to copy string %s", addr_un.sun_path);
-    goto _FAILED;
+    goto _SOCKET_FAILED;
   }
 
   if (chmod(self->socket_path_result, self->permissions) < 0) {
     GST_ERROR_OBJECT(self, "failed to chmod %s - %d", addr_un.sun_path, self->permissions);
-    goto _FAILED;
+    goto _SOCKET_FAILED;
   }
 
   if (listen(self->socket_fd, DEFAULT_BACKLOG) < 0) {
     GST_ERROR_OBJECT(self, "failed to listen");
-    goto _FAILED;
+    goto _SOCKET_FAILED;
+  }
+
+  GST_INFO_OBJECT(self, "socket fd [%d]", self->socket_fd);
+
+  return TRUE;
+
+_SOCKET_FAILED:
+  if (self->socket_fd > INIT_FD) {
+    shutdown(self->socket_fd, SHUT_RDWR);
+    close(self->socket_fd);
+    self->socket_fd = INIT_FD;
+  }
+
+  return FALSE;
+}
+
+
+static gboolean __init_shared_memory(GstTizenipcSink *self, guint shm_size)
+{
+  int i = 0;
+  gchar shm_path[32] = {'\0',};
+
+  if (shm_size == 0) {
+    GST_INFO_OBJECT(self, "shm size is 0");
+    return TRUE;
   }
 
-  /* create shared memory */
-  i = 0;
   do {
     snprintf(shm_path, 32, "%s.%d", DEFAULT_SHM_PATH, i++);
     self->shm_fd = shm_open(shm_path, O_RDWR|O_CREAT|O_EXCL, self->permissions);
@@ -190,7 +211,7 @@ static gboolean _prepare_tizenipc_sink(GstTizenipcSink *self, guint shm_size)
 
   if (self->shm_fd < 0) {
     GST_ERROR_OBJECT(self, "failed to open shared memory [%s], errno [%d]", shm_path, errno);
-    goto _FAILED;
+    goto _SHARED_MEMORY_FAILED;
   }
 
   if (self->shm_path) {
@@ -201,33 +222,66 @@ static gboolean _prepare_tizenipc_sink(GstTizenipcSink *self, guint shm_size)
   self->shm_path = g_strdup(shm_path);
   if (self->shm_path == NULL) {
     GST_ERROR_OBJECT(self, "failed to copy shared memory path");
-    goto _FAILED;
+    goto _SHARED_MEMORY_FAILED;
   }
 
   if (ftruncate(self->shm_fd, shm_size) < 0) {
     GST_ERROR_OBJECT(self, "failed to resize shm to %d", shm_size);
-    goto _FAILED;
+    goto _SHARED_MEMORY_FAILED;
   }
 
   self->shm_mapped_area = (gchar *)mmap(NULL,
-                                        shm_size,
-                                        PROT_READ | PROT_WRITE,
-                                        MAP_SHARED,
-                                        self->shm_fd,
-                                        0);
+    shm_size,
+    PROT_READ | PROT_WRITE,
+    MAP_SHARED,
+    self->shm_fd,
+    0);
   if (self->shm_mapped_area == MAP_FAILED) {
     GST_ERROR_OBJECT(self, "failed to mmap for shared memory");
-    goto _FAILED;
+    goto _SHARED_MEMORY_FAILED;
   }
 
   self->shm_mapped_size = shm_size;
 
+  GST_INFO_OBJECT(self, "shared memory size [%d]", self->shm_mapped_size);
+
+  return TRUE;
+
+_SHARED_MEMORY_FAILED:
+  if (self->shm_fd > INIT_FD) {
+    close(self->shm_fd);
+    self->shm_fd = INIT_FD;
+  }
+
+  return FALSE;
+}
+
+
+static gboolean _prepare_tizenipc_sink(GstTizenipcSink *self, guint shm_size)
+{
+  if (self == NULL) {
+    GST_ERROR("NULL handle");
+    return FALSE;
+  }
+
+  GST_INFO_OBJECT(self, "start - socket path [%s], shared memory size [%u]",
+    self->socket_path, shm_size);
+
+  /* socket */
+  if (!__init_socket(self))
+    return FALSE;
+
+  /* shared memory */
+  if (!__init_shared_memory(self, shm_size))
+    goto _FAILED;
+
   /* create gst poll and thread for poll */
   self->poll = gst_poll_new(TRUE);
   if (self->poll == NULL) {
     GST_ERROR_OBJECT(self, "failed to create gst poll");
     goto _FAILED;
   }
+
   gst_poll_fd_init(&self->pollfd);
   self->pollfd.fd = self->socket_fd;
   gst_poll_add_fd(self->poll, &self->pollfd);
@@ -254,14 +308,14 @@ _FAILED:
     self->poll = NULL;
   }
 
-  if (self->shm_fd > -1) {
+  if (self->shm_fd > INIT_FD) {
     close(self->shm_fd);
-    self->shm_fd = -1;
+    self->shm_fd = INIT_FD;
   }
 
-  if (self->socket_fd > -1) {
+  if (self->socket_fd > INIT_FD) {
     close(self->socket_fd);
-    self->socket_fd = -1;
+    self->socket_fd = INIT_FD;
   }
 
   return FALSE;
@@ -272,7 +326,7 @@ static gboolean _add_buffer_to_list(GstTizenipcSink *self, GstBuffer *buf, int *
 {
   int i = 0;
   int j = 0;
-  GstTizenipcBuffer *sended_buffer = NULL;
+  GstTizenipcBuffer *buffer_list = NULL;
 
   if (self == NULL || buf == NULL || tbm_key == NULL) {
     GST_ERROR("NULL parameter %p, %p, %p", self, buf, tbm_key);
@@ -281,23 +335,23 @@ static gboolean _add_buffer_to_list(GstTizenipcSink *self, GstBuffer *buf, int *
 
   g_mutex_lock(&self->buffer_lock);
 
-  sended_buffer = self->sended_buffer;
+  buffer_list = self->buffer_list;
 
-  for (i = 0 ; i < GST_TIZENIPC_BUFFER_MAX ; i++) {
+  for (i = 0 ; i < IPC_BUFFER_MAX ; i++) {
     /* find empty space */
-    if (sended_buffer[i].gst_buf == NULL) {
-      self->sended_buffer_count++;
+    if (buffer_list[i].gst_buf == NULL) {
+      self->buffer_list_count++;
 
       GST_DEBUG_OBJECT(self, "insert buffer(key[0] %d) to index %d, count %d",
-                             tbm_key[0], i, self->sended_buffer_count);
+                             tbm_key[0], i, self->buffer_list_count);
 
       /* ref gst buffer and set tbm key */
       gst_buffer_ref(buf);
-      sended_buffer[i].gst_buf = buf;
+      buffer_list[i].gst_buf = buf;
 
-      for (j = 0 ; j < MM_VIDEO_BUFFER_PLANE_MAX ; j++) {
+      for (j = 0 ; j < TBM_SURF_PLANE_MAX ; j++) {
         if (tbm_key[j] > 0) {
-          sended_buffer[i].tbm_key[j] = tbm_key[j];
+          buffer_list[i].tbm_key[j] = tbm_key[j];
         } else {
           break;
         }
@@ -320,7 +374,7 @@ static gboolean _add_buffer_to_list(GstTizenipcSink *self, GstBuffer *buf, int *
 static gboolean _remove_buffer_from_list(GstTizenipcSink *self, int *tbm_key)
 {
   int i = 0;
-  GstTizenipcBuffer *sended_buffer = NULL;
+  GstTizenipcBuffer *buffer_list = NULL;
 
   if (self == NULL || tbm_key == NULL) {
     GST_ERROR("NULL parameter %p, %p", self, tbm_key);
@@ -329,31 +383,31 @@ static gboolean _remove_buffer_from_list(GstTizenipcSink *self, int *tbm_key)
 
   g_mutex_lock(&self->buffer_lock);
 
-  sended_buffer = self->sended_buffer;
+  buffer_list = self->buffer_list;
 
-  for (i = 0 ; i < GST_TIZENIPC_BUFFER_MAX ; i++) {
+  for (i = 0 ; i < IPC_BUFFER_MAX ; i++) {
     /* find matched buffer info */
-    if (sended_buffer[i].tbm_key[0] == tbm_key[0] &&
-        sended_buffer[i].tbm_key[1] == tbm_key[1] &&
-        sended_buffer[i].tbm_key[2] == tbm_key[2] &&
-        sended_buffer[i].tbm_key[3] == tbm_key[3]) {
+    if (buffer_list[i].tbm_key[0] == tbm_key[0] &&
+        buffer_list[i].tbm_key[1] == tbm_key[1] &&
+        buffer_list[i].tbm_key[2] == tbm_key[2] &&
+        buffer_list[i].tbm_key[3] == tbm_key[3]) {
       /* remove buffer info and unref gst buffer */
-      self->sended_buffer_count--;
+      self->buffer_list_count--;
 
       GST_DEBUG_OBJECT(self, "gst buffer %p for key[0] %d, count %d",
-                             sended_buffer[i].gst_buf, tbm_key[0], self->sended_buffer_count);
+                             buffer_list[i].gst_buf, tbm_key[0], self->buffer_list_count);
 
-      if (sended_buffer[i].gst_buf) {
-        gst_buffer_unref(sended_buffer[i].gst_buf);
-        sended_buffer[i].gst_buf = NULL;
+      if (buffer_list[i].gst_buf) {
+        gst_buffer_unref(buffer_list[i].gst_buf);
+        buffer_list[i].gst_buf = NULL;
       } else {
         GST_WARNING_OBJECT(self, "no gst buffer for key[0] %d", tbm_key[0]);
       }
 
-      sended_buffer[i].tbm_key[0] = 0;
-      sended_buffer[i].tbm_key[1] = 0;
-      sended_buffer[i].tbm_key[2] = 0;
-      sended_buffer[i].tbm_key[3] = 0;
+      buffer_list[i].tbm_key[0] = 0;
+      buffer_list[i].tbm_key[1] = 0;
+      buffer_list[i].tbm_key[2] = 0;
+      buffer_list[i].tbm_key[3] = 0;
 
       g_cond_signal(&self->buffer_cond);
       g_mutex_unlock(&self->buffer_lock);
@@ -383,20 +437,20 @@ static void gst_tizenipc_sink_init(GstTizenipcSink *self)
   g_mutex_init(&self->ipc_lock);
   g_cond_init(&self->ipc_cond);
 
-  self->socket_fd = -1;
-  self->client_fd = -1;
-  self->shm_fd = -1;
+  self->socket_fd = INIT_FD;
+  self->client_fd = INIT_FD;
+  self->shm_fd = INIT_FD;
   self->shm_mapped_area = MAP_FAILED;
   self->is_connected = FALSE;
   self->permissions = DEFAULT_PERMISSIONS;
+
   self->socket_path = g_strdup(DEFAULT_SOCKET_PATH);
-  if (self->socket_path == NULL) {
+  if (self->socket_path == NULL)
     GST_ERROR_OBJECT(self, "failed to dup socket path [%s]", DEFAULT_SOCKET_PATH);
-  }
-  self->sended_buffer = g_new0(GstTizenipcBuffer, GST_TIZENIPC_BUFFER_MAX);
-  if (self->sended_buffer == NULL) {
-    GST_ERROR_OBJECT(self, "failed to alloc sended_buffer");
-  }
+
+  self->buffer_list = g_new0(GstTizenipcBuffer, IPC_BUFFER_MAX);
+  if (self->buffer_list == NULL)
+    GST_ERROR_OBJECT(self, "failed to alloc buffer_list");
 
   return;
 }
@@ -499,19 +553,19 @@ static void gst_tizenipc_sink_finalize(GObject *object)
   g_mutex_clear(&self->buffer_lock);
   g_cond_clear(&self->buffer_cond);
 
-  if (self->socket_path) {
-    g_free(self->socket_path);
-    self->socket_path = NULL;
-  }
+  g_free(self->socket_path);
+  self->socket_path = NULL;
 
-  if (self->socket_path_result) {
-    g_free(self->socket_path_result);
-    self->socket_path_result = NULL;
-  }
+  g_free(self->socket_path_result);
+  self->socket_path_result = NULL;
 
-  if (self->shm_path) {
-    g_free(self->shm_path);
-    self->shm_path = NULL;
+  g_free(self->shm_path);
+  self->shm_path = NULL;
+
+  if (self->caps_string) {
+    GST_INFO_OBJECT(self, "release caps string [%s]", self->caps_string);
+    g_free(self->caps_string);
+    self->caps_string = NULL;
   }
 
   G_OBJECT_CLASS(parent_class)->finalize(object);
@@ -543,10 +597,7 @@ static void gst_tizenipc_sink_set_property(GObject *object, guint prop_id,
     {
       gchar *temp_string = g_value_dup_string(value);
       if (temp_string) {
-        if (self->socket_path) {
-          g_free(self->socket_path);
-          self->socket_path = NULL;
-        }
+        g_free(self->socket_path);
         self->socket_path = temp_string;
       } else {
         GST_ERROR_OBJECT(object, "failed to copy string [%s]", g_value_get_string(value));
@@ -620,9 +671,9 @@ static gboolean gst_tizenipc_sink_start(GstBaseSink *bsink)
 
   /* check socket path and buffer list */
   if (self->socket_path == NULL ||
-      self->sended_buffer == NULL) {
-    GST_ERROR_OBJECT(self, "socket path[%p] or sended buffer [%p] is NULL",
-                           self->socket_path, self->sended_buffer);
+      self->buffer_list == NULL) {
+    GST_ERROR_OBJECT(self, "socket path[%p] or buffer_list [%p] is NULL",
+                           self->socket_path, self->buffer_list);
     return FALSE;
   }
 
@@ -648,7 +699,24 @@ static gboolean gst_tizenipc_sink_stop(GstBaseSink *bsink)
     return FALSE;
   }
 
-  GST_INFO_OBJECT(self, "start");
+  /* wait for buffer */
+  g_mutex_lock(&self->buffer_lock);
+
+  GST_INFO_OBJECT(self, "start - not returned buffer %d", self->buffer_list_count);
+
+  while (self->buffer_list_count > 0) {
+    wait_end_time = g_get_monotonic_time () + BUFFER_WAIT_TIMEOUT;
+    if (!g_cond_wait_until(&self->buffer_cond, &self->buffer_lock, wait_end_time)) {
+      GST_WARNING_OBJECT(self, "wait timeout - current count %d",
+                               self->buffer_list_count);
+      break;
+    } else {
+      GST_WARNING_OBJECT(self, "signal received - current count %d",
+                               self->buffer_list_count);
+    }
+  }
+
+  g_mutex_unlock(&self->buffer_lock);
 
   /* stop poll thread */
   self->poll_thread_run = FALSE;
@@ -665,23 +733,6 @@ static gboolean gst_tizenipc_sink_stop(GstBaseSink *bsink)
     GST_WARNING_OBJECT(self, "no poll thread");
   }
 
-  /* wait for sended buffer */
-  g_mutex_lock(&self->buffer_lock);
-
-  while (self->sended_buffer_count > 0) {
-    wait_end_time = g_get_monotonic_time () + BUFFER_WAIT_TIMEOUT;
-    if (!g_cond_wait_until(&self->buffer_cond, &self->buffer_lock, wait_end_time)) {
-      GST_WARNING_OBJECT(self, "wait timeout - current count %d",
-                               self->sended_buffer_count);
-      break;
-    } else {
-      GST_WARNING_OBJECT(self, "signal received - current count %d",
-                               self->sended_buffer_count);
-    }
-  }
-
-  g_mutex_unlock(&self->buffer_lock);
-
   /* close client */
   if (self->client_fd >= 0) {
     GST_INFO_OBJECT(self, "close client fd %d", self->client_fd);
@@ -689,7 +740,7 @@ static gboolean gst_tizenipc_sink_stop(GstBaseSink *bsink)
     shutdown(self->client_fd, SHUT_RDWR);
     close(self->client_fd);
     g_signal_emit(self, signals[SIGNAL_CLIENT_DISCONNECTED], 0, self->client_fd);
-    self->client_fd = -1;
+    self->client_fd = INIT_FD;
   } else {
     GST_WARNING_OBJECT(self, "no client");
   }
@@ -703,7 +754,7 @@ static gboolean gst_tizenipc_sink_stop(GstBaseSink *bsink)
     }
 
     close(self->shm_fd);
-    self->shm_fd = -1;
+    self->shm_fd = INIT_FD;
 
     if (self->shm_path) {
       shm_unlink(self->shm_path);
@@ -728,7 +779,7 @@ static gboolean gst_tizenipc_sink_stop(GstBaseSink *bsink)
 
     shutdown(self->socket_fd, SHUT_RDWR);
     close(self->socket_fd);
-    self->socket_fd = -1;
+    self->socket_fd = INIT_FD;
   } else {
     GST_WARNING_OBJECT(self, "socket is not opened");
   }
@@ -747,11 +798,9 @@ static GstFlowReturn gst_tizenipc_sink_render(GstBaseSink *bsink, GstBuffer *buf
 {
   GstTizenipcSink *self = NULL;
   GstTizenipcMessage msg = {0, };
-  MMVideoBuffer *mm_buf = NULL;
   GstMemory *memory = NULL;
   GstMapInfo map_info = GST_MAP_INFO_INIT;
   gint64 wait_end_time = 0;
-  int tbm_key[MM_VIDEO_BUFFER_PLANE_MAX] = {0, };
   int i = 0;
 
   if (bsink == NULL) {
@@ -782,11 +831,16 @@ static GstFlowReturn gst_tizenipc_sink_render(GstBaseSink *bsink, GstBuffer *buf
     goto _SKIP_BUFFER;
   }
 
+  memory = gst_buffer_peek_memory(buf, 0);
+  if (!memory) {
+    GST_WARNING_OBJECT(self, "failed to peek memory 0 for %p", buf);
+    goto _SKIP_BUFFER;
+  }
+
   if (self->is_normal_format) {
-    memory = gst_buffer_peek_memory(buf, 0);
-    if (memory == NULL) {
-      GST_WARNING_OBJECT(self, "failed to peek memory 0 for %p", buf);
-      goto _SKIP_BUFFER;
+    if (self->shm_mapped_area == MAP_FAILED) {
+      GST_ERROR_OBJECT(self, "no mapped area");
+      return GST_FLOW_ERROR;
     }
 
     if (gst_memory_map(memory, &map_info, GST_MAP_READ) == FALSE) {
@@ -806,62 +860,40 @@ static GstFlowReturn gst_tizenipc_sink_render(GstBaseSink *bsink, GstBuffer *buf
     msg.id = TIZEN_IPC_BUFFER_NEW;
     msg.size = map_info.size;
   } else {
-    /* get mm_buf from gst buffer */
-    if (gst_buffer_n_memory(buf) <= 1) {
-      GST_WARNING_OBJECT(self, "invalid memory number %d", gst_buffer_n_memory(buf));
-      goto _SKIP_BUFFER;
-    }
+    int num_bos = 0;
+    tbm_bo bo = NULL;
 
-    memory = gst_buffer_peek_memory(buf, 1);
-    if (memory == NULL) {
-      GST_WARNING_OBJECT(self, "failed to peek memory 1 for %p", buf);
-      goto _SKIP_BUFFER;
-    }
+    /* set command type */
+    msg.id = TIZEN_IPC_BUFFER_NEW;
 
-    if (gst_memory_map(memory, &map_info, GST_MAP_READ) == FALSE) {
-      GST_WARNING_OBJECT(self, "failed to map memory %p", memory);
-      goto _SKIP_BUFFER;
-    }
+    /* get number of bo */
+    num_bos = gst_tizen_memory_get_num_bos(memory);
 
-    mm_buf = (MMVideoBuffer *)map_info.data;
+    GST_LOG_OBJECT(self, "Tizen memory[%p] : number of bo %d", memory, num_bos);
 
-    gst_memory_unmap(memory, &map_info);
+    /* get bo and export to deliver to client process */
+    for (i = 0 ; i < num_bos ; i++) {
+      bo = gst_tizen_memory_get_bos(memory, i);
+      if (!bo) {
+        GST_ERROR_OBJECT(self, "failed to get bo for index %d", i);
+        continue;
+      }
 
-    if (mm_buf == NULL) {
-      GST_WARNING_OBJECT(self, "NULL mm_buf");
-      goto _SKIP_BUFFER;
-    }
+      msg.tbm_key[i] = tbm_bo_export(bo);
 
-    GST_LOG_OBJECT(self, "MMVideoBuffer info - %p, num handle %d",
-      mm_buf, mm_buf->handle_num);
-
-    /* export bo to pass buffer to client process */
-    for (i = 0 ; i < mm_buf->handle_num ; i++) {
-      if (mm_buf->handle.bo[i]) {
-        tbm_key[i] = tbm_bo_export(mm_buf->handle.bo[i]);
-        GST_LOG_OBJECT(self, "export tbm key[index:%d] %d", i, tbm_key[i]);
-        if (tbm_key[i] <= 0) {
-          GST_ERROR_OBJECT(self, "failed to export bo[%d] %p", i, mm_buf->handle.bo[i]);
-          goto _SKIP_BUFFER;
-        }
-      } else {
-        break;
+      GST_LOG_OBJECT(self, "export tbm key[index:%d] %d", i, msg.tbm_key[i]);
+
+      if (msg.tbm_key[i] <= 0) {
+        GST_ERROR_OBJECT(self, "failed to export bo[%d] %p", i, bo);
+        goto _SKIP_BUFFER;
       }
     }
 
     /* keep and send buffer */
-    if (_add_buffer_to_list(self, buf, tbm_key) == FALSE) {
-      GST_ERROR_OBJECT(self, "failed to add to list for buffer %p and key[0] %d", buf, tbm_key[0]);
+    if (_add_buffer_to_list(self, buf, msg.tbm_key) == FALSE) {
+      GST_ERROR_OBJECT(self, "failed to add to list for buffer %p and key[0] %d", buf, msg.tbm_key[0]);
       goto _SKIP_BUFFER;
     }
-
-    /* set command type and size */
-    msg.id = TIZEN_IPC_BUFFER_NEW;
-    msg.size = sizeof(MMVideoBuffer) + sizeof(tbm_key);
-
-    /* copy zero copy info to shared memory */
-    memcpy(self->shm_mapped_area, mm_buf, sizeof(MMVideoBuffer));
-    memcpy(self->shm_mapped_area + sizeof(MMVideoBuffer), tbm_key, sizeof(tbm_key));
   }
 
   /* send data */
@@ -894,7 +926,7 @@ static GstFlowReturn gst_tizenipc_sink_render(GstBaseSink *bsink, GstBuffer *buf
 
 _SKIP_BUFFER_AFTER_ADD_TO_LIST:
   if (!self->is_normal_format)
-    _remove_buffer_from_list(self, tbm_key);
+    _remove_buffer_from_list(self, msg.tbm_key);
 
 _SKIP_BUFFER:
   g_mutex_unlock(&self->ipc_lock);
@@ -920,7 +952,7 @@ static gboolean gst_tizenipc_sink_event(GstBaseSink *bsink, GstEvent *event)
 
   switch (GST_EVENT_TYPE(event)) {
     case GST_EVENT_EOS:
-      /* wait for sended buffer */
+      /* wait for buffer */
       break;
     default:
       break;
@@ -945,7 +977,6 @@ static gboolean gst_tizenipc_sink_unlock_stop(GstBaseSink *bsink)
 static gboolean gst_tizenipc_sink_set_caps(GstBaseSink *bsink, GstCaps *caps)
 {
   GstTizenipcSink *self = NULL;
-  GstStructure *structure = NULL;
 
   if (bsink == NULL) {
     GST_ERROR("NULL object");
@@ -960,49 +991,56 @@ static gboolean gst_tizenipc_sink_set_caps(GstBaseSink *bsink, GstCaps *caps)
 
   GST_INFO_OBJECT(self, "start - caps [%"GST_PTR_FORMAT"]", caps);
 
-  self->is_normal_format = TRUE;
-
-  structure = gst_caps_get_structure(caps, 0);
-  if (structure == NULL) {
-    GST_ERROR_OBJECT(self, "failed to get structure from caps [%"GST_PTR_FORMAT"]", caps);
+  /* get GstVideoInfo */
+  gst_video_info_init(&self->video_info);
+  if (!gst_video_info_from_caps(&self->video_info, caps)) {
+    GST_ERROR_OBJECT(bsink, "failed to get video info from caps[%p,%"GST_PTR_FORMAT"]",
+      caps, caps);
     return FALSE;
   }
 
-  if (!gst_structure_has_name(structure, "video/x-raw")) {
-    GST_ERROR_OBJECT(self, "not supported caps [%"GST_PTR_FORMAT"]", caps);
+  self->is_normal_format = TRUE;
+  self->format = GST_VIDEO_INFO_FORMAT(&self->video_info);
+  self->width = GST_VIDEO_INFO_WIDTH(&self->video_info);
+  self->height = GST_VIDEO_INFO_HEIGHT(&self->video_info);
+
+  switch (self->format) {
+  case GST_VIDEO_FORMAT_SN12:
+  case GST_VIDEO_FORMAT_SN21:
+  case GST_VIDEO_FORMAT_S420:
+  case GST_VIDEO_FORMAT_ST12:
+  case GST_VIDEO_FORMAT_SR32:
+  case GST_VIDEO_FORMAT_STV0:
+  case GST_VIDEO_FORMAT_STV1:
+    self->shm_size = 0;
+    self->is_normal_format = FALSE;
+    break;
+  case GST_VIDEO_FORMAT_I420:
+  case GST_VIDEO_FORMAT_YV12:
+    self->shm_size = (self->width * self->height * 3) >> 1;
+    break;
+  case GST_VIDEO_FORMAT_YUY2:
+  case GST_VIDEO_FORMAT_UYVY:
+    self->shm_size = (self->width * self->height) << 1;
+    break;
+  default:
+    GST_ERROR_OBJECT(self, "unsupported format [%d]", self->format);
     return FALSE;
   }
 
-  self->format_string = gst_structure_get_string(structure, "format");
-  if (self->format_string == NULL) {
-    GST_ERROR_OBJECT(self, "failed to get format from caps [%"GST_PTR_FORMAT"]", caps);
-    return FALSE;
-  }
+  GST_INFO_OBJECT(self, "format %d, size %dx%d, shm size %d",
+    self->format, self->width, self->height, self->shm_size);
 
-  if (!gst_structure_get_int(structure, "width", &self->width) ||
-    !gst_structure_get_int(structure, "height", &self->height)) {
-    GST_ERROR_OBJECT(self, "failed to get width, height from caps [%"GST_PTR_FORMAT"]", caps);
-    return FALSE;
+  if (self->caps_string) {
+    GST_INFO_OBJECT(self, "release caps string [%s]", self->caps_string);
+    g_free(self->caps_string);
+    self->caps_string = NULL;
   }
 
-  if (!strcmp(self->format_string, "SN12") || !strcmp(self->format_string, "SN21") ||
-    !strcmp(self->format_string, "SYVY") || !strcmp(self->format_string, "SUYV") ||
-    !strcmp(self->format_string, "S420")) {
-    self->shm_size = sizeof(MMVideoBuffer) + (sizeof(int) * MM_VIDEO_BUFFER_PLANE_MAX);
-    self->is_normal_format = FALSE;
-  } else if (!strcmp(self->format_string, "NV12") || !strcmp(self->format_string, "NV21") ||
-    !strcmp(self->format_string, "I420") || !strcmp(self->format_string, "YV12")) {
-    self->shm_size = (self->width * self->height * 3) >> 1;
-  } else if (!strcmp(self->format_string, "YUYV") || !strcmp(self->format_string, "YUY2") ||
-    !strcmp(self->format_string, "UYVY")) {
-    self->shm_size = (self->width * self->height) << 1;
-  } else {
-    GST_ERROR_OBJECT(self, "unsupported format [%s]", self->format_string);
-    return FALSE;
-  }
+  /* get caps string */
+  self->caps_string = gst_caps_to_string(caps);
 
-  GST_INFO_OBJECT(self, "format %s, size %dx%d, shm size %d",
-    self->format_string, self->width, self->height, self->shm_size);
+  GST_INFO_OBJECT(self, "caps [%s]", self->caps_string);
 
   /* create socket and shared memory for sending buffer */
   if (!_prepare_tizenipc_sink(self, self->shm_size)) {
@@ -1093,50 +1131,73 @@ static gpointer _gst_poll_thread_func(gpointer data)
 
       GST_INFO_OBJECT(self, "client accpeted : fd %d", self->client_fd);
 
-      /* send shard memory size */
-      msg.id = TIZEN_IPC_SHM_SIZE;
-      msg.size = self->shm_mapped_size;
-      if (send(self->client_fd, &msg, sizeof(GstTizenipcMessage), MSG_NOSIGNAL) != sizeof(GstTizenipcMessage)) {
-        GST_ERROR_OBJECT(self, "failed to send shard memory size");
-        close(self->client_fd);
-        self->client_fd = -1;
-        g_mutex_unlock(&self->ipc_lock);
-        continue;
+      if (self->shm_mapped_size > 0) {
+        /* send shard memory size */
+        msg.id = TIZEN_IPC_SHM_SIZE;
+        msg.size = self->shm_mapped_size;
+        if (send(self->client_fd, &msg, sizeof(GstTizenipcMessage), MSG_NOSIGNAL) != sizeof(GstTizenipcMessage)) {
+          GST_ERROR_OBJECT(self, "failed to send shard memory size");
+          close(self->client_fd);
+          self->client_fd = INIT_FD;
+          g_mutex_unlock(&self->ipc_lock);
+          continue;
+        }
+
+        /* send shard memory path */
+        msg.id = TIZEN_IPC_SHM_PATH;
+        msg.size = strlen(self->shm_path) + 1;
+        if (send(self->client_fd, &msg, sizeof(GstTizenipcMessage), MSG_NOSIGNAL) != sizeof(GstTizenipcMessage)) {
+          GST_ERROR_OBJECT(self, "failed to send shard memory path 1");
+          close(self->client_fd);
+          self->client_fd = INIT_FD;
+          g_mutex_unlock(&self->ipc_lock);
+          continue;
+        }
+
+        if (send(self->client_fd, self->shm_path, msg.size, MSG_NOSIGNAL) != msg.size) {
+          GST_ERROR_OBJECT(self, "failed to send shard memory path 2");
+          close(self->client_fd);
+          self->client_fd = INIT_FD;
+          g_mutex_unlock(&self->ipc_lock);
+          continue;
+        }
+
+        GST_INFO_OBJECT(self, "send shm path done - %s", self->shm_path);
       }
 
-      /* send shard memory path */
-      msg.id = TIZEN_IPC_SHM_PATH;
-      msg.size = strlen(self->shm_path) + 1;
+      /* send buffer type */
+      msg.id = TIZEN_IPC_BUFFER_TYPE;
+      msg.type = self->is_normal_format ? BUFFER_TYPE_NORMAL : BUFFER_TYPE_ZERO_COPY;
       if (send(self->client_fd, &msg, sizeof(GstTizenipcMessage), MSG_NOSIGNAL) != sizeof(GstTizenipcMessage)) {
-        GST_ERROR_OBJECT(self, "failed to send shard memory path 1");
+        GST_ERROR_OBJECT(self, "failed to send buffer type");
         close(self->client_fd);
-        self->client_fd = -1;
+        self->client_fd = INIT_FD;
         g_mutex_unlock(&self->ipc_lock);
         continue;
       }
 
-      if (send(self->client_fd, self->shm_path, strlen(self->shm_path) + 1, MSG_NOSIGNAL) != (strlen(self->shm_path) + 1)) {
-        GST_ERROR_OBJECT(self, "failed to send shard memory path 2");
+      GST_INFO_OBJECT(self, "send buffer type done - %d", msg.type);
+
+      /* send caps string */
+      msg.id = TIZEN_IPC_BUFFER_CAPS;
+      msg.size = strlen(self->caps_string) + 1;
+      if (send(self->client_fd, &msg, sizeof(GstTizenipcMessage), MSG_NOSIGNAL) != sizeof(GstTizenipcMessage)) {
+        GST_ERROR_OBJECT(self, "failed to send caps string 1");
         close(self->client_fd);
-        self->client_fd = -1;
+        self->client_fd = INIT_FD;
         g_mutex_unlock(&self->ipc_lock);
         continue;
       }
 
-      GST_INFO_OBJECT(self, "send shm path done - %s", self->shm_path);
-
-      /* send buffer type */
-      msg.id = TIZEN_IPC_BUFFER_TYPE;
-      msg.type = self->is_normal_format ? BUFFER_TYPE_NORMAL : BUFFER_TYPE_ZERO_COPY;
-      if (send(self->client_fd, &msg, sizeof(GstTizenipcMessage), MSG_NOSIGNAL) != sizeof(GstTizenipcMessage)) {
-        GST_ERROR_OBJECT(self, "failed to send buffer type");
+      if (send(self->client_fd, self->caps_string, msg.size, MSG_NOSIGNAL) != msg.size) {
+        GST_ERROR_OBJECT(self, "failed to send caps string 2");
         close(self->client_fd);
-        self->client_fd = -1;
+        self->client_fd = INIT_FD;
         g_mutex_unlock(&self->ipc_lock);
         continue;
       }
 
-      GST_INFO_OBJECT(self, "send buffer type done - %d", msg.type);
+      GST_INFO_OBJECT(self, "send caps string done - %s", self->caps_string);
 
       gst_poll_fd_init(&self->client_pollfd);
       self->client_pollfd.fd = self->client_fd;
@@ -1150,7 +1211,7 @@ static gpointer _gst_poll_thread_func(gpointer data)
       continue;
     }
 
-    if (self->client_fd > -1) {
+    if (self->client_fd > INIT_FD) {
       if (gst_poll_fd_has_closed(self->poll, &self->client_pollfd)) {
         GST_WARNING_OBJECT(self, "client is gone, closing");
         goto close_client;
@@ -1210,8 +1271,10 @@ static gpointer _gst_poll_thread_func(gpointer data)
       GST_INFO_OBJECT(self, "close client fd %d", self->client_fd);
 
       gst_poll_remove_fd(self->poll, &self->client_pollfd);
+
+      shutdown(self->client_fd, SHUT_RDWR);
       close(self->client_fd);
-      self->client_fd = -1;
+      self->client_fd = INIT_FD;
 
       g_mutex_unlock(&self->ipc_lock);
 
index cd329e0..46d6dd8 100644 (file)
@@ -24,8 +24,9 @@
 
 #include <gst/gst.h>
 #include <gst/base/gstbasesink.h>
+#include <gst/video/video-info.h>
 #include <tbm_bufmgr.h>
-#include <mm_types.h>
+#include "gsttizenipc.h"
 
 G_BEGIN_DECLS
 
@@ -36,20 +37,19 @@ G_BEGIN_DECLS
 #define GST_IS_TIZENIPC_SINK_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE((klass), GST_TYPE_TIZENIPC_SINK))
 #define GST_TIZENIPC_SINK_GET_CLASS(inst) (G_TYPE_INSTANCE_GET_CLASS((inst), GST_TYPE_TIZENIPC_SINK, GstTizenipcSinkClass))
 
-#define GST_TIZENIPC_BUFFER_MAX 30
-
 typedef struct _GstTizenipcSink GstTizenipcSink;
 typedef struct _GstTizenipcSinkClass GstTizenipcSinkClass;
 typedef struct _GstTizenipcBuffer GstTizenipcBuffer;
-typedef struct _GstTizenipcMessage GstTizenipcMessage;
 
 struct _GstTizenipcSink {
   GstBaseSink parent;
 
-  const gchar *format_string;
+  gchar *caps_string;
+  GstVideoFormat format;
   gint width;
   gint height;
   gboolean is_normal_format;
+  GstVideoInfo video_info;
 
   /* ipc */
   int socket_fd;
@@ -75,8 +75,8 @@ struct _GstTizenipcSink {
   guint permissions;
 
   /* buffer management */
-  GstTizenipcBuffer *sended_buffer;
-  guint sended_buffer_count;
+  GstTizenipcBuffer *buffer_list;
+  guint buffer_list_count;
   GMutex buffer_lock;
   GCond buffer_cond;
 };
@@ -87,32 +87,7 @@ struct _GstTizenipcSinkClass {
 
 struct _GstTizenipcBuffer {
   GstBuffer *gst_buf;
-  guint tbm_key[MM_VIDEO_BUFFER_PLANE_MAX];
-};
-
-
-typedef enum {
-  TIZEN_IPC_SHM_PATH = 0,
-  TIZEN_IPC_SHM_SIZE,
-  TIZEN_IPC_BUFFER_TYPE,
-  TIZEN_IPC_BUFFER_NEW,
-  TIZEN_IPC_BUFFER_RECEIVED,
-  TIZEN_IPC_BUFFER_RELEASE,
-  TIZEN_IPC_CLOSE_CLIENT
-} TizenIPCID;
-
-typedef enum {
-  BUFFER_TYPE_NORMAL = 0,
-  BUFFER_TYPE_ZERO_COPY
-} BufferType;
-
-struct _GstTizenipcMessage {
-  TizenIPCID id;
-  union {
-    BufferType type;
-    int size;
-    int tbm_key[MM_VIDEO_BUFFER_PLANE_MAX];
-  };
+  guint tbm_key[TBM_SURF_PLANE_MAX];
 };
 
 GType
index f10b428..a7a3f01 100644 (file)
 #include <sys/socket.h>
 #include <sys/un.h>
 #include <fcntl.h>
+#include <gst/allocators/gsttizenmemory.h>
 #include "gsttizenipcsrc.h"
 
 #define DEFAULT_SOCKET_PATH "/tmp/tizenipc.0"
-#define DEFAULT_SHM_PATH    "/tizenipcshm"
+#define DEFAULT_SHM_PATH    "/tmp/tizenipcshm"
 #define DEFAULT_PERMISSIONS (S_IRUSR|S_IWUSR|S_IRGRP)
 #define DEFAULT_BACKLOG     5
 #define BUFFER_WAIT_TIMEOUT     (G_TIME_SPAN_MILLISECOND * 3000)
@@ -68,6 +69,10 @@ enum {
 };
 
 
+static GstBuffer *_tizenipc_src_buffer_new(GstTizenipcSrc *self, GstTizenipcMessage *recv_msg);
+static void       _tizenipc_src_buffer_finalize(GstTizenipcSrcBuffer *buffer);
+static gboolean   _tizenipc_get_tbm_format(GstVideoFormat video_format, guint32 *tbm_format);
+
 
 static void gst_tizenipc_src_finalize(GObject *object);
 static void gst_tizenipc_src_set_property(GObject *object, guint prop_id,
@@ -76,14 +81,48 @@ static void gst_tizenipc_src_get_property(GObject *object, guint prop_id,
                                           GValue *value, GParamSpec *pspec);
 static gboolean gst_tizenipc_src_start(GstBaseSrc *bsrc);
 static gboolean gst_tizenipc_src_stop(GstBaseSrc *bsrc);
-static GstFlowReturn gst_tizenipc_src_create(GstPushSrc *psrc, GstBuffer **outbuf);
 static gboolean gst_tizenipc_src_unlock(GstBaseSrc *bsrc);
 static gboolean gst_tizenipc_src_unlock_stop(GstBaseSrc *bsrc);
+static GstFlowReturn gst_tizenipc_src_create(GstPushSrc *psrc, GstBuffer **outbuf);
 static GstStateChangeReturn gst_tizenipc_src_change_state(GstElement *element, GstStateChange transition);
-static void gst_tizenipc_src_buffer_finalize(GstTizenipcSrcBuffer *buffer);
 
 
 
+static gboolean _tizenipc_get_tbm_format(GstVideoFormat video_format, guint32 *tbm_format)
+{
+  if (!tbm_format) {
+    GST_ERROR("NULL param");
+    return FALSE;
+  }
+
+  switch(video_format) {
+  case GST_VIDEO_FORMAT_I420:
+  case GST_VIDEO_FORMAT_S420:
+    *tbm_format = TBM_FORMAT_YUV420;
+    break;
+  case GST_VIDEO_FORMAT_NV12:
+  case GST_VIDEO_FORMAT_SN12:
+    *tbm_format = TBM_FORMAT_NV12;
+    break;
+  case GST_VIDEO_FORMAT_NV21:
+  case GST_VIDEO_FORMAT_SN21:
+    *tbm_format = TBM_FORMAT_NV21;
+    break;
+  case GST_VIDEO_FORMAT_YUY2:
+    *tbm_format = TBM_FORMAT_YUYV;
+    break;
+  case GST_VIDEO_FORMAT_UYVY:
+    *tbm_format = TBM_FORMAT_UYVY;
+    break;
+  default:
+    GST_ERROR("unhandled format %d", video_format);
+    return FALSE;
+  }
+
+  return TRUE;
+}
+
+
 static gboolean _tizenipc_src_prepare_to_read(GstTizenipcSrc *self)
 {
   struct sockaddr_un addr_un;
@@ -106,7 +145,7 @@ static gboolean _tizenipc_src_prepare_to_read(GstTizenipcSrc *self)
     return FALSE;
   }
 
-  GST_INFO_OBJECT(self, "start");
+  GST_INFO_OBJECT(self, "start - socket path [%s]", self->socket_path);
 
   /* socket connection */
   self->socket_fd = socket(PF_UNIX, SOCK_STREAM, 0);
@@ -121,7 +160,7 @@ static gboolean _tizenipc_src_prepare_to_read(GstTizenipcSrc *self)
     goto _PREPARE_FAILED;
   }
 
-  if (fcntl(self->socket_fd, F_SETFL, flags|FD_CLOEXEC) < 0) {
+  if (fcntl(self->socket_fd, F_SETFL, flags | FD_CLOEXEC) < 0) {
     GST_ERROR_OBJECT(self, "failed to fcntl F_SETFL FD_CLOEXEC for socket fd %d", self->socket_fd);
     goto _PREPARE_FAILED;
   }
@@ -133,7 +172,7 @@ static gboolean _tizenipc_src_prepare_to_read(GstTizenipcSrc *self)
   address_len = sizeof(addr_un);
 
   if (connect(self->socket_fd, address, address_len) < 0) {
-    GST_ERROR_OBJECT(self, "failed to connect for socket fd %d", self->socket_fd);
+    GST_ERROR_OBJECT(self, "failed to connect for socket fd %d, errno %d", self->socket_fd, errno);
     goto _PREPARE_FAILED;
   }
 
@@ -152,7 +191,7 @@ _PREPARE_FAILED:
   if (self->socket_fd >= 0) {
     shutdown(self->socket_fd, SHUT_RDWR);
     close(self->socket_fd);
-    self->socket_fd = -1;
+    self->socket_fd = INIT_FD;
   }
 
   if (self->socket_path) {
@@ -209,21 +248,17 @@ static gboolean _tizenipc_src_stop_to_read(GstTizenipcSrc *self)
 
     shutdown(self->socket_fd, SHUT_RDWR);
     close(self->socket_fd);
-    self->socket_fd = -1;
+    self->socket_fd = INIT_FD;
   }
 
-  if (self->socket_path) {
-    unlink(self->socket_path);
-  }
-
-  if (self->shm_mapped_area) {
+  if (self->shm_mapped_area != MAP_FAILED) {
     munmap(self->shm_mapped_area, self->shm_mapped_size);
     self->shm_mapped_area = MAP_FAILED;
   }
 
   if (self->shm_fd) {
     close(self->shm_fd);
-    self->shm_fd = -1;
+    self->shm_fd = INIT_FD;
   }
 
   GST_INFO_OBJECT(self, "done");
@@ -241,20 +276,24 @@ static void gst_tizenipc_src_init(GstTizenipcSrc *self)
   g_mutex_init(&self->buffer_lock);
   g_cond_init(&self->buffer_cond);
 
-  self->socket_fd = -1;
-  self->shm_fd = -1;
+  self->socket_fd = INIT_FD;
+  self->shm_fd = INIT_FD;
   self->shm_mapped_area = MAP_FAILED;
   self->bufmgr = tbm_bufmgr_init(-1);
+
   self->socket_path = g_strdup(DEFAULT_SOCKET_PATH);
-  if (self->socket_path == NULL) {
+  if (self->socket_path == NULL)
     GST_ERROR_OBJECT(self, "failed to dup socket path [%s]", DEFAULT_SOCKET_PATH);
-  }
+
   self->poll = gst_poll_new(TRUE);
-  if (self->poll == NULL) {
+  if (self->poll == NULL)
     GST_ERROR_OBJECT(self, "failed to get gst poll");
-  } else {
+  else
     gst_poll_fd_init(&self->pollfd);
-  }
+
+  self->allocator = gst_tizen_allocator_new();
+  if (!self->allocator)
+    GST_ERROR_OBJECT(self, "tizen allocator new failed");
 
   return;
 }
@@ -340,15 +379,11 @@ static void gst_tizenipc_src_finalize(GObject *object)
   g_mutex_clear(&self->buffer_lock);
   g_cond_clear(&self->buffer_cond);
 
-  if (self->socket_path) {
-    g_free(self->socket_path);
-    self->socket_path = NULL;
-  }
+  g_free(self->socket_path);
+  self->socket_path = NULL;
 
-  if (self->shm_path) {
-    g_free(self->shm_path);
-    self->shm_path = NULL;
-  }
+  g_free(self->shm_path);
+  self->shm_path = NULL;
 
   if (self->poll) {
     gst_poll_free(self->poll);
@@ -360,6 +395,12 @@ static void gst_tizenipc_src_finalize(GObject *object)
     self->bufmgr = NULL;
   }
 
+  if (self->caps_string) {
+    GST_INFO_OBJECT(self, "release caps string [%s]", self->caps_string);
+    g_free(self->caps_string);
+    self->caps_string = NULL;
+  }
+
   GST_INFO_OBJECT(self, "done");
 
   G_OBJECT_CLASS(parent_class)->finalize(object);
@@ -393,11 +434,9 @@ static void gst_tizenipc_src_set_property(GObject *object, guint prop_id,
 
       temp_string = g_value_dup_string(value);
       if (temp_string) {
-        if (self->socket_path) {
-          g_free(self->socket_path);
-          self->socket_path = NULL;
-        }
+        g_free(self->socket_path);
         self->socket_path = temp_string;
+        GST_INFO_OBJECT(object, "socket path [%s]", self->socket_path);
       } else {
         GST_ERROR_OBJECT(object, "failed to copy string [%s]", g_value_get_string(value));
       }
@@ -510,11 +549,10 @@ static gboolean gst_tizenipc_src_stop(GstBaseSrc *bsrc)
 }
 
 
-static void gst_tizenipc_src_buffer_finalize(GstTizenipcSrcBuffer *ipc_buf)
+static void _tizenipc_src_buffer_finalize(GstTizenipcSrcBuffer *ipc_buf)
 {
   GstTizenipcSrc *self = NULL;
   GstTizenipcMessage send_msg = {0,};
-  MMVideoBuffer *mm_buf = NULL;
   int i = 0;
   int send_len = 0;
 
@@ -524,17 +562,15 @@ static void gst_tizenipc_src_buffer_finalize(GstTizenipcSrcBuffer *ipc_buf)
   }
 
   self = ipc_buf->self;
-  mm_buf = ipc_buf->mm_buf;
-
   if (self == NULL) {
     GST_ERROR("NULL handle");
     goto _BUFFER_FINALIZE_DONE;
   }
 
   /* send message to sink for current tbm key */
-  if (self->socket_fd > -1) {
+  if (self->socket_fd > INIT_FD) {
     send_msg.id = TIZEN_IPC_BUFFER_RELEASE;
-    memcpy(send_msg.tbm_key, ipc_buf->tbm_key, sizeof(int) * MM_VIDEO_BUFFER_PLANE_MAX);
+    memcpy(send_msg.tbm_key, ipc_buf->tbm_key, sizeof(int) * TBM_SURF_PLANE_MAX);
     send_len = send(self->socket_fd, &send_msg, sizeof(GstTizenipcMessage), MSG_NOSIGNAL);
     if (send_len != sizeof(GstTizenipcMessage)) {
       GST_ERROR_OBJECT(self, "send failed : BUFFER_RELEASE key[0] %d", send_msg.tbm_key[0]);
@@ -547,7 +583,7 @@ static void gst_tizenipc_src_buffer_finalize(GstTizenipcSrcBuffer *ipc_buf)
   g_mutex_lock(&self->buffer_lock);
 
   GST_DEBUG_OBJECT(self, "live buffer(tbm key[0] %d) count %d -> %d",
-                         ipc_buf->tbm_key[0], self->live_buffer_count, self->live_buffer_count-1);
+    ipc_buf->tbm_key[0], self->live_buffer_count, self->live_buffer_count - 1);
 
   self->live_buffer_count--;
   g_cond_signal(&self->buffer_cond);
@@ -558,18 +594,18 @@ static void gst_tizenipc_src_buffer_finalize(GstTizenipcSrcBuffer *ipc_buf)
   self = NULL;
 
 _BUFFER_FINALIZE_DONE:
-  if (mm_buf) {
-    for (i = 0 ; i < mm_buf->handle_num ; i++) {
-      if (mm_buf->handle.bo[i]) {
-        tbm_bo_unref(mm_buf->handle.bo[i]);
-        mm_buf->handle.bo[i] = NULL;
-      } else {
-        break;
-      }
-    }
+  if (ipc_buf->t_surface) {
+    tbm_surface_destroy(ipc_buf->t_surface);
+    ipc_buf->t_surface = NULL;
+  }
 
-    free(mm_buf);
-    mm_buf = NULL;
+  for (i = 0 ; ipc_buf->bos[i] ; i++) {
+    if (ipc_buf->bos[i]) {
+      tbm_bo_unref(ipc_buf->bos[i]);
+      ipc_buf->bos[i] = NULL;
+    } else {
+      break;
+    }
   }
 
   free(ipc_buf);
@@ -579,17 +615,145 @@ _BUFFER_FINALIZE_DONE:
 }
 
 
+static GstBuffer *_tizenipc_src_buffer_new(GstTizenipcSrc *self, GstTizenipcMessage *recv_msg)
+{
+  int i = 0;
+  int num_bos = 0;
+  void *normal_buffer_data = NULL;
+
+  GstBuffer *buffer = NULL;
+  GstMemory *memory = NULL;
+
+  GstTizenipcSrcBuffer *ipc_buf = NULL;
+  GstTizenipcMessage send_msg = {0,};
+
+  if (!self || !recv_msg) {
+    GST_ERROR_OBJECT(self, "NULL param %p %p", self, recv_msg);
+    return NULL;
+  }
+
+  /* create empty buffer */
+  buffer = gst_buffer_new();
+  if (!buffer) {
+    GST_ERROR_OBJECT(self, "buffer failed");
+    return NULL;
+  }
+
+  /* get new buffer from sink */
+  if (self->is_normal_format) {
+    if (self->shm_mapped_area == MAP_FAILED) {
+      GST_ERROR_OBJECT(self, "no mapped area");
+      goto _BUFFER_NEW_FAILED;
+    }
+    /* non-zero-copy case */
+    normal_buffer_data = (void *)malloc(recv_msg->size);
+    if (!normal_buffer_data) {
+      GST_ERROR_OBJECT(self, "normal buffer[%d] failed", recv_msg->size);
+      goto _BUFFER_NEW_FAILED;
+    }
+
+    memcpy(normal_buffer_data, self->shm_mapped_area, recv_msg->size);
+
+    /* create GstMemory */
+    memory = gst_memory_new_wrapped(0,
+      normal_buffer_data, recv_msg->size, 0,
+      recv_msg->size, normal_buffer_data, free);
+  } else {
+    /* zero-copy case */
+    ipc_buf = g_new0(GstTizenipcSrcBuffer, 1);
+    if (!ipc_buf) {
+      GST_ERROR_OBJECT(self, "GstTizenipcSrcBuffer alloc failed");
+      goto _BUFFER_NEW_FAILED;
+    }
+
+    ipc_buf->gst_buf = buffer;
+    ipc_buf->self = gst_object_ref(self);
+
+    /* get tbm key from message */
+    memcpy(send_msg.tbm_key, recv_msg->tbm_key, sizeof(int) * TBM_SURF_PLANE_MAX);
+
+    /* import tbm bo */
+    for (i = 0 ; i < TBM_SURF_PLANE_MAX && send_msg.tbm_key[i] > 0 ; i++) {
+      ipc_buf->bos[i] = tbm_bo_import(self->bufmgr, send_msg.tbm_key[i]);
+      if (ipc_buf->bos[i] == NULL) {
+        GST_ERROR_OBJECT(self, "bo import failed for key [%d]", send_msg.tbm_key[i]);
+        goto _BUFFER_NEW_FAILED;
+      }
+
+      ipc_buf->tbm_key[i] = send_msg.tbm_key[i];
+
+      num_bos++;
+    }
+
+    /* create tbm surface */
+    ipc_buf->t_surface = tbm_surface_internal_create_with_bos(&self->ts_info, ipc_buf->bos, num_bos);
+    if (!ipc_buf->t_surface) {
+      GST_ERROR_OBJECT(self, "tbm surface create failed");
+      goto _BUFFER_NEW_FAILED;
+    }
+
+    /* create GstMemory */
+    memory = gst_tizen_allocator_alloc_surface(self->allocator,
+      &self->video_info,
+      ipc_buf->t_surface,
+      (gpointer)ipc_buf,
+      (GDestroyNotify)_tizenipc_src_buffer_finalize);
+
+    if (memory) {
+      g_mutex_lock(&self->buffer_lock);
+      self->live_buffer_count++;
+      GST_DEBUG_OBJECT(self, "gst buffer %p, live count %d", buffer, self->live_buffer_count);
+      g_mutex_unlock(&self->buffer_lock);
+    }
+  }
+
+  if (!memory) {
+    GST_ERROR_OBJECT(self, "gst memory create failed");
+    goto _BUFFER_NEW_FAILED;
+  }
+
+  /* append memory */
+  gst_buffer_append_memory(buffer, memory);
+
+  GST_LOG_OBJECT(self, "new buffer %p", buffer);
+
+  return buffer;
+
+_BUFFER_NEW_FAILED:
+  if (ipc_buf) {
+    for (i = 0 ; i < TBM_SURF_PLANE_MAX ; i++) {
+      if (ipc_buf->bos[i]) {
+        GST_WARNING_OBJECT(self, "release imported bo[%d] %p", i, ipc_buf->bos[i]);
+        tbm_bo_unref(ipc_buf->bos[i]);
+        ipc_buf->bos[i] = NULL;
+      }
+    }
+
+    gst_object_unref(ipc_buf->self);
+    ipc_buf->self = NULL;
+
+    g_free(ipc_buf);
+    ipc_buf = NULL;
+  }
+
+  if (normal_buffer_data) {
+    free(normal_buffer_data);
+    normal_buffer_data = NULL;
+  }
+
+  gst_buffer_unref(buffer);
+  buffer = NULL;
+
+  return NULL;
+}
+
+
 static GstFlowReturn gst_tizenipc_src_create(GstPushSrc *psrc, GstBuffer **outbuf)
 {
   GstTizenipcSrc *self = NULL;
-  GstTizenipcSrcBuffer *ipc_buf = NULL;
   GstTizenipcMessage recv_msg = {0,};
   GstTizenipcMessage send_msg = {0,};
-  MMVideoBuffer *mm_buf = NULL;
   GstBuffer *gst_buf = NULL;
-  GstMemory *gst_memory = NULL;
-  void *normal_buffer_data = NULL;
-  int i = 0;
   int recv_len = 0;
   int send_len = 0;
 
@@ -650,54 +814,7 @@ again:
 
     /* handle message */
     if (recv_msg.id == TIZEN_IPC_BUFFER_NEW) {
-      /* get new buffer from sink */
-      if (self->shm_mapped_area == MAP_FAILED) {
-        GST_ERROR_OBJECT(self, "shared memory is not mapped");
-        return GST_FLOW_ERROR;
-      }
-
-      if (!self->is_normal_format) {
-        mm_buf = (MMVideoBuffer *)malloc(sizeof(MMVideoBuffer));
-        if (mm_buf) {
-          memcpy(mm_buf, self->shm_mapped_area, sizeof(MMVideoBuffer));
-          memcpy(send_msg.tbm_key, self->shm_mapped_area + sizeof(MMVideoBuffer), sizeof(int) * MM_VIDEO_BUFFER_PLANE_MAX);
-
-          for (i = 0 ; i < MM_VIDEO_BUFFER_PLANE_MAX ; i++) {
-            if (send_msg.tbm_key[i] > 0) {
-              tbm_bo_handle bo_handle = {0, };
-
-              GST_LOG_OBJECT(self, "received tbm key[%d] %d", i, send_msg.tbm_key[i]);
-
-              /* import bo from tbm key */
-              mm_buf->handle.bo[i] = tbm_bo_import(self->bufmgr, send_msg.tbm_key[i]);
-              if (mm_buf->handle.bo[i] == NULL) {
-                GST_ERROR_OBJECT(self, "failed to import bo for tbm key %d", send_msg.tbm_key[i]);
-                break;
-              }
-
-              /* get user address */
-              bo_handle = tbm_bo_get_handle(mm_buf->handle.bo[i], TBM_DEVICE_CPU);
-              if (bo_handle.ptr == NULL) {
-                GST_ERROR_OBJECT(self, "failed to get user address for bo %p, key %d",
-                  mm_buf->handle.bo[i], send_msg.tbm_key[i]);
-                break;
-              }
-              mm_buf->data[i] = bo_handle.ptr;
-            } else {
-              break;
-            }
-          }
-        } else {
-          GST_ERROR_OBJECT(self, "failed to alloc MMVideoBuffer");
-        }
-      } else {
-        normal_buffer_data = (void *)malloc(recv_msg.size);
-        if (normal_buffer_data) {
-          memcpy(normal_buffer_data, self->shm_mapped_area, recv_msg.size);
-        } else {
-          GST_ERROR_OBJECT(self, "failed to alloc new buffer data - size %d", recv_msg.size);
-        }
-      }
+      gst_buf = _tizenipc_src_buffer_new(self, &recv_msg);
 
       /* send received message */
       send_msg.id = TIZEN_IPC_BUFFER_RECEIVED;
@@ -705,12 +822,10 @@ again:
       GST_OBJECT_LOCK(self);
 
       send_len = send(self->socket_fd, &send_msg, sizeof(GstTizenipcMessage), MSG_NOSIGNAL);
+      if (send_len != sizeof(GstTizenipcMessage))
+        GST_ERROR_OBJECT(self, "failed to send RECEIVED message");
 
       GST_OBJECT_UNLOCK(self);
-
-      if (send_len != sizeof(GstTizenipcMessage)) {
-        GST_ERROR_OBJECT(self, "failed to send RECEIVED message");
-      }
     } else if (recv_msg.id == TIZEN_IPC_SHM_PATH) {
       gchar shm_path[32] = {'\0',};
 
@@ -754,7 +869,7 @@ again:
       if (self->shm_mapped_area == MAP_FAILED) {
         GST_ERROR_OBJECT(self, "failed to mmap shared memory for fd %d", self->shm_fd);
         close(self->shm_fd);
-        self->shm_fd = -1;
+        self->shm_fd = INIT_FD;
         return GST_FLOW_ERROR;
       }
 
@@ -771,113 +886,91 @@ again:
       self->is_normal_format = (recv_msg.type == BUFFER_TYPE_NORMAL) ? TRUE : FALSE;
       GST_INFO_OBJECT(self, "is normal format? %d", self->is_normal_format);
       goto again;
-    } else {
-      GST_WARNING_OBJECT(self, "unknown message : id %d", recv_msg.id);
-      goto again;
-    }
-  }
+    } else if (recv_msg.id == TIZEN_IPC_BUFFER_CAPS) {
+      int tbm_ret = 0;
+      guint32 tbm_format = 0;
+      GstCaps *caps = NULL;
+      tbm_surface_h t_surface = NULL;
+
+      if (recv_msg.size <= 0) {
+        GST_ERROR_OBJECT(self, "invalid caps_string size %d", recv_msg.size);
+        return GST_FLOW_ERROR;
+      }
 
-  if (mm_buf == NULL && normal_buffer_data == NULL) {
-    GST_ERROR_OBJECT(self, "All buffers are NULL");
-    return GST_FLOW_ERROR;
-  }
+      g_free(self->caps_string);
+      self->caps_string = NULL;
 
-  /* make gst buffer with mm_buf */
-  gst_buf = gst_buffer_new();
-  if (gst_buf == NULL) {
-    GST_ERROR_OBJECT(self, "failed to create gst buffer");
-    goto _CREATE_FAILED;
-  }
+      self->caps_string = (gchar *)g_malloc((gsize)recv_msg.size);
+      if (!self->caps_string) {
+        GST_ERROR_OBJECT(self, "caps_string allocation failed");
+        return GST_FLOW_ERROR;
+      }
 
-  /* default memory */
-  if (mm_buf) {
-    gst_memory = gst_memory_new_wrapped(0,
-      mm_buf->data[0], mm_buf->size[0], 0,
-      mm_buf->size[0], NULL, NULL);
-  } else {
-    gst_memory = gst_memory_new_wrapped(0,
-      normal_buffer_data, recv_msg.size, 0,
-      recv_msg.size, normal_buffer_data, free);
-  }
-  if (gst_memory == NULL) {
-    GST_ERROR_OBJECT(self, "failed to create default gst memory");
-    goto _CREATE_FAILED;
-  }
-
-  gst_buffer_append_memory(gst_buf, gst_memory);
-  gst_memory = NULL;
-
-  if (mm_buf) {
-    /* mm_buf memory */
-    gst_memory = gst_memory_new_wrapped(0,
-      mm_buf, sizeof(MMVideoBuffer), 0,
-      sizeof(MMVideoBuffer), mm_buf, NULL);
-    if (gst_memory == NULL) {
-      GST_ERROR_OBJECT(self, "failed to create gst memory for mm_buf");
-      goto _CREATE_FAILED;
-    }
+      /* get caps string */
+      recv_len = recv(self->socket_fd, self->caps_string, recv_msg.size, 0);
+      if (recv_len != recv_msg.size) {
+        GST_ERROR_OBJECT(self, "failed to receive message from sink %d : %d",
+                               recv_len, recv_msg.size);
+        return GST_FLOW_ERROR;
+      }
 
-    gst_buffer_append_memory(gst_buf, gst_memory);
-    gst_memory = NULL;
+      GST_INFO_OBJECT(self, "caps string from sink [%s]", self->caps_string);
 
-    /* ipc_buf memory */
-    ipc_buf = (GstTizenipcSrcBuffer *)malloc(sizeof(GstTizenipcSrcBuffer));
-    if (ipc_buf == NULL) {
-      GST_ERROR_OBJECT(self, "failed to create GstTizenipcsrcBuffer");
-      goto _CREATE_FAILED;
-    }
+      /* get caps from string */
+      caps = gst_caps_from_string(self->caps_string);
+      if (!caps) {
+        GST_ERROR_OBJECT(self, "failed to get caps from string");
+        return GST_FLOW_ERROR;
+      }
 
-    ipc_buf->self = gst_object_ref(self);
-    ipc_buf->gst_buf = gst_buf;
-    ipc_buf->mm_buf = mm_buf;
-    memcpy(ipc_buf->tbm_key, send_msg.tbm_key, sizeof(int) * MM_VIDEO_BUFFER_PLANE_MAX);
-
-    gst_memory = gst_memory_new_wrapped(0,
-      ipc_buf, sizeof(GstTizenipcSrcBuffer), 0,
-      sizeof(GstTizenipcSrcBuffer), ipc_buf,
-      (GDestroyNotify)gst_tizenipc_src_buffer_finalize);
-    if (gst_memory == NULL) {
-      GST_ERROR_OBJECT(self, "failed to create gst memory for ipc_buf");
-      goto _CREATE_FAILED;
-    }
+      /* get video info from caps */
+      if (!gst_video_info_from_caps(&self->video_info, caps)) {
+        GST_ERROR_OBJECT(self, "get video info failed (caps[%s])", self->caps_string);
+        return GST_FLOW_ERROR;
+      }
 
-    gst_buffer_append_memory(gst_buf, gst_memory);
-    gst_memory = NULL;
+      /* get tbm format */
+      if (!_tizenipc_get_tbm_format(GST_VIDEO_INFO_FORMAT(&self->video_info), &tbm_format)) {
+        GST_ERROR_OBJECT(self, "get tbm format failed - video format %d", GST_VIDEO_INFO_FORMAT(&self->video_info));
+        return GST_FLOW_ERROR;
+      }
 
-    g_mutex_lock(&self->buffer_lock);
-    self->live_buffer_count++;
-    GST_DEBUG_OBJECT(self, "gst buffer %p, live count %d", gst_buf, self->live_buffer_count);
-    g_mutex_unlock(&self->buffer_lock);
-  } else {
-    GST_DEBUG_OBJECT(self, "normal buffer create done - size %d", recv_msg.size);
-  }
+      /* get tbm surface info */
+      t_surface = tbm_surface_create(GST_VIDEO_INFO_WIDTH(&self->video_info),
+        GST_VIDEO_INFO_HEIGHT(&self->video_info), tbm_format);
+      if (!t_surface) {
+        GST_ERROR_OBJECT(self, "tbm surface failed");
+        return GST_FLOW_ERROR;
+      }
 
-  *outbuf = gst_buf;
+      memset(&self->ts_info, 0x0, sizeof(tbm_surface_info_s));
 
-  return GST_FLOW_OK;
+      tbm_ret = tbm_surface_get_info(t_surface, &self->ts_info);
 
-_CREATE_FAILED:
-  if (ipc_buf) {
-    free(ipc_buf);
-    ipc_buf = NULL;
-  }
+      tbm_surface_destroy(t_surface);
+      t_surface = NULL;
 
-  if (mm_buf) {
-    free(mm_buf);
-    mm_buf = NULL;
-  }
+      if (tbm_ret != TBM_SURFACE_ERROR_NONE) {
+        GST_ERROR_OBJECT(self, "tbm_surface_get_info failed. 0x%x", tbm_ret);
+        return GST_FLOW_ERROR;
+      }
 
-  if (gst_buf) {
-    gst_buffer_unref(gst_buf);
-    gst_buf = NULL;
+      GST_INFO_OBJECT(self, "video/tbm surface info done.");
+      goto again;
+    } else {
+      GST_WARNING_OBJECT(self, "unknown message : id %d", recv_msg.id);
+      goto again;
+    }
   }
 
-  if (normal_buffer_data) {
-    free(normal_buffer_data);
-    normal_buffer_data = NULL;
+  if (!gst_buf) {
+    GST_ERROR_OBJECT(self, "no buffer");
+    return GST_FLOW_ERROR;
   }
 
-  return GST_FLOW_ERROR;
+  *outbuf = gst_buf;
+
+  return GST_FLOW_OK;
 }
 
 
index 80c976c..bdbfff2 100644 (file)
@@ -25,8 +25,9 @@
 #include <gst/gst.h>
 #include <gst/base/gstpushsrc.h>
 #include <gst/base/gstbasesrc.h>
-#include <tbm_bufmgr.h>
-#include <mm_types.h>
+#include <tbm_surface.h>
+#include <tbm_surface_internal.h>
+#include "gsttizenipc.h"
 
 G_BEGIN_DECLS
 
@@ -37,17 +38,19 @@ G_BEGIN_DECLS
 #define GST_IS_TIZENIPC_SRC_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE((klass), GST_TYPE_TIZENIPC_SRC))
 #define GST_TIZENIPC_SRC_GET_CLASS(inst) (G_TYPE_INSTANCE_GET_CLASS((inst), GST_TYPE_TIZENIPC_SRC, GstTizenipcSrcClass))
 
-#define GST_TIZENIPC_BUFFER_MAX 30
-
 typedef struct _GstTizenipcSrc GstTizenipcSrc;
 typedef struct _GstTizenipcSrcClass GstTizenipcSrcClass;
 typedef struct _GstTizenipcSrcBuffer GstTizenipcSrcBuffer;
-typedef struct _GstTizenipcMessage GstTizenipcMessage;
 
 struct _GstTizenipcSrc {
   GstPushSrc parent;
 
+  /* buffer */
   gboolean is_normal_format;
+  gchar *caps_string;
+  GstAllocator *allocator;
+  GstVideoInfo video_info;
+  tbm_surface_info_s ts_info;
 
   /* ipc */
   int socket_fd;
@@ -75,34 +78,10 @@ struct _GstTizenipcSrcClass {
 
 struct _GstTizenipcSrcBuffer {
   GstBuffer *gst_buf;
-  MMVideoBuffer *mm_buf;
-  int tbm_key[MM_VIDEO_BUFFER_PLANE_MAX];
   GstTizenipcSrc *self;
-};
-
-
-typedef enum {
-  TIZEN_IPC_SHM_PATH = 0,
-  TIZEN_IPC_SHM_SIZE,
-  TIZEN_IPC_BUFFER_TYPE,
-  TIZEN_IPC_BUFFER_NEW,
-  TIZEN_IPC_BUFFER_RECEIVED,
-  TIZEN_IPC_BUFFER_RELEASE,
-  TIZEN_IPC_CLOSE_CLIENT
-} TizenIPCID;
-
-typedef enum {
-  BUFFER_TYPE_NORMAL = 0,
-  BUFFER_TYPE_ZERO_COPY
-} BufferType;
-
-struct _GstTizenipcMessage {
-  TizenIPCID id;
-  union {
-    BufferType type;
-    int size;
-    int tbm_key[MM_VIDEO_BUFFER_PLANE_MAX];
-  };
+  tbm_bo bos[TBM_SURF_PLANE_MAX];
+  int tbm_key[TBM_SURF_PLANE_MAX];
+  tbm_surface_h t_surface;
 };
 
 GType