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, [
%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\
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)
#include <string.h>
+#ifdef GST_TBM_SUPPORT
+#include <mm_types.h>
+#include <tbm_bufmgr.h>
+#endif
+
/* signals */
enum
{
PROP_SHM_SIZE,
PROP_WAIT_FOR_CONNECTION,
PROP_BUFFER_TIME
+#ifdef GST_TBM_SUPPORT
+ ,PROP_USE_TBM
+#endif
};
struct GstShmClient
"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,
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;
}
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;
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) {
}
+#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));
"%" 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;
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 ();
GstShmSinkAllocator *allocator;
GstAllocationParams params;
+#ifdef GST_TBM_SUPPORT
+ gboolean use_tbm;
+#endif
};
struct _GstShmSinkClass
#include <string.h>
+#ifdef GST_TBM_SUPPORT
+#include <mm_types.h>
+#endif
/* signals */
enum
{
PROP_0,
PROP_SOCKET_PATH,
PROP_IS_LIVE
+#ifdef GST_TBM_SUPPORT
+ ,PROP_USE_TBM
+#endif
};
struct GstShmBuffer
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));
{
self->poll = gst_poll_new (TRUE);
gst_poll_fd_init (&self->pollfd);
+ self->h_bufmgr = tbm_bufmgr_init(-1);
}
static void
gst_poll_free (self->poll);
g_free (self->socket_path);
+ tbm_bufmgr_deinit(self->h_bufmgr);
G_OBJECT_CLASS (parent_class)->finalize (object);
}
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;
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;
return TRUE;
}
-
static void
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)
{
*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;
}
#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 \
GstFlowReturn flow_return;
gboolean unlocked;
+#ifdef GST_TBM_SUPPORT
+ gboolean use_tbm;
+ tbm_bufmgr h_bufmgr;
+#endif
};
struct _GstShmSrcClass