From 0d5d2f54c511216174d57eb3ae9165765edfe49d Mon Sep 17 00:00:00 2001 From: Barun Kumar Singh Date: Mon, 14 Dec 2015 14:54:55 +0530 Subject: [PATCH 01/16] Fixing plane size calculation. Signed-off-by: Barun Kr. Singh Change-Id: If5f871dded37908ac1b50e58b3dddf6b90029795 --- waylandsrc/src/gstwaylandsrc.c | 76 ++++++++++++++++++++++++++++++++++-------- waylandsrc/src/gstwaylandsrc.h | 25 ++++++++++++++ 2 files changed, 87 insertions(+), 14 deletions(-) diff --git a/waylandsrc/src/gstwaylandsrc.c b/waylandsrc/src/gstwaylandsrc.c index 57c05df..e1a1e0a 100644 --- a/waylandsrc/src/gstwaylandsrc.c +++ b/waylandsrc/src/gstwaylandsrc.c @@ -168,27 +168,75 @@ static const struct tizen_screenmirror_listener mirror_listener = { mirror_handle_stop }; -#define ALIGN(x, a) (((x) + (a) - 1) & ~((a) - 1)) -#define DIV_ROUND_UP(n,d) (((n) + (d) - 1) / (d)) +int new_calc_plane(int width, int height) +{ + int mbX, mbY; + + mbX = DIV_ROUND_UP(width, S5P_FIMV_NUM_PIXELS_IN_MB_ROW); + mbY = DIV_ROUND_UP(height, S5P_FIMV_NUM_PIXELS_IN_MB_COL); + + if (width * height < S5P_FIMV_MAX_FRAME_SIZE) + mbY = (mbY + 1) / 2 * 2; + + return ((mbX * S5P_FIMV_NUM_PIXELS_IN_MB_COL) * + (mbY * S5P_FIMV_NUM_PIXELS_IN_MB_ROW)); +} + +int new_calc_yplane(int width, int height) +{ + return (ALIGN_TO_4KB(new_calc_plane(width, height) + + S5P_FIMV_D_ALIGN_PLANE_SIZE)); +} + +int new_calc_uvplane(int width, int height) +{ + return (ALIGN_TO_4KB((new_calc_plane(width, height) >> 1) + + S5P_FIMV_D_ALIGN_PLANE_SIZE)); +} -int calc_yplane(int width, int height) +int +calc_plane(int width, int height) { int mbX, mbY; - mbX = DIV_ROUND_UP(width, 16); - mbY = DIV_ROUND_UP(height, 16); + mbX = ALIGN(width, S5P_FIMV_NV12MT_HALIGN); + mbY = ALIGN(height, S5P_FIMV_NV12MT_VALIGN); - return (ALIGN((mbX * mbY) * 256, 256) + 256); + return ALIGN(mbX * mbY, S5P_FIMV_DEC_BUF_ALIGN); } -int calc_uvplane(int width, int height) +int +calc_yplane(int width, int height) { int mbX, mbY; - mbX = DIV_ROUND_UP(width, 16); - mbY = DIV_ROUND_UP(height, 16); + mbX = ALIGN(width + 24, S5P_FIMV_NV12MT_HALIGN); + mbY = ALIGN(height + 16, S5P_FIMV_NV12MT_VALIGN); - return (ALIGN((mbX * mbY) * 128, 256) + 128); + return ALIGN(mbX * mbY, S5P_FIMV_DEC_BUF_ALIGN); +} + +int +calc_uvplane(int width, int height) +{ + int mbX, mbY; + + mbX = ALIGN(width + 16, S5P_FIMV_NV12MT_HALIGN); + mbY = ALIGN(height + 4, S5P_FIMV_NV12MT_VALIGN); + + return ALIGN((mbX * mbY)>>1, S5P_FIMV_DEC_BUF_ALIGN); +} + +int +gst_calculate_y_size(int width, int height) +{ + return CHOOSE_MAX_SIZE(calc_yplane(width,height),new_calc_yplane(width,height)); +} + +int +gst_calculate_uv_size(int width, int height) +{ + return CHOOSE_MAX_SIZE(calc_uvplane(width,height),new_calc_uvplane(width,height)); } static void @@ -295,8 +343,8 @@ mirror_handle_dequeued (void *data, mm_video_buf->handle.bo[1] = out_buffer->bo[1]; GST_INFO_OBJECT (src, "BO : %p %p", mm_video_buf->handle.bo[0], mm_video_buf->handle.bo[1]); - mm_video_buf->size[0] = calc_yplane(src->width, src->height); /*(src->width * src->height);*/ - mm_video_buf->size[1] = calc_uvplane(src->width, src->height); /*(src->width * (src->height >> 1));*/ + mm_video_buf->size[0] = gst_calculate_y_size(src->width, src->height); /*(src->width * src->height);*/ + mm_video_buf->size[1] = gst_calculate_uv_size(src->width, src->height); /*(src->width * (src->height >> 1));*/ mm_video_buf->width[0] = src->width; mm_video_buf->height[0] = src->height; mm_video_buf->format = MM_PIXEL_FORMAT_NV12; @@ -591,10 +639,10 @@ tbm_buffer_create (GstWaylandSrc * src) info.bpp = tbm_surface_internal_get_bpp(info.format); info.num_planes = 2; info.planes[0].stride = info.width; - info.planes[0].size = calc_yplane(info.planes[0].stride, info.height);//info.planes[0].stride * info.height + info.planes[0].size = gst_calculate_y_size(info.planes[0].stride, info.height);//info.planes[0].stride * info.height info.planes[0].offset = 0; info.planes[1].stride = info.width; - info.planes[1].size = calc_uvplane(info.planes[1].stride, info.height);//info.planes[1].stride * (info.height >> 1); + info.planes[1].size = gst_calculate_uv_size(info.planes[1].stride, info.height);//info.planes[1].stride * (info.height >> 1); info.planes[1].offset = 0; info.size = info.planes[0].size + info.planes[1].size; diff --git a/waylandsrc/src/gstwaylandsrc.h b/waylandsrc/src/gstwaylandsrc.h index 7b2256d..e4b637b 100644 --- a/waylandsrc/src/gstwaylandsrc.h +++ b/waylandsrc/src/gstwaylandsrc.h @@ -130,5 +130,30 @@ GType gst_wayland_src_get_type (void) G_GNUC_CONST; +/*MFC Buffer alignment macros*/ +#define S5P_FIMV_DEC_BUF_ALIGN (8 * 1024) +#define S5P_FIMV_ENC_BUF_ALIGN (8 * 1024) +#define S5P_FIMV_NV12M_HALIGN 16 +#define S5P_FIMV_NV12M_LVALIGN 16 +#define S5P_FIMV_NV12M_CVALIGN 8 +#define S5P_FIMV_NV12MT_HALIGN 128 +#define S5P_FIMV_NV12MT_VALIGN 64 +#define S5P_FIMV_NV12M_SALIGN 2048 +#define S5P_FIMV_NV12MT_SALIGN 8192 + +#define ALIGN(x, a) (((x) + (a) - 1) & ~((a) - 1)) + +/* Buffer alignment defines */ +#define SZ_1M 0x00100000 +#define S5P_FIMV_D_ALIGN_PLANE_SIZE 64 + +#define S5P_FIMV_MAX_FRAME_SIZE (2 * SZ_1M) +#define S5P_FIMV_NUM_PIXELS_IN_MB_ROW 16 +#define S5P_FIMV_NUM_PIXELS_IN_MB_COL 16 + +/* Macro */ +#define ALIGN_TO_4KB(x) ((((x) + (1 << 12) - 1) >> 12) << 12) +#define DIV_ROUND_UP(n,d) (((n) + (d) - 1) / (d)) +#define CHOOSE_MAX_SIZE(a,b) ((a) > (b) ? (a) : (b)) G_END_DECLS #endif /* __GST_WAYLAND_VIDEO_SOURCE_H__ */ -- 2.7.4 From fa114f84b7ce6456a2b22c8558852fb69b5726d7 Mon Sep 17 00:00:00 2001 From: Hyunjun Ko Date: Wed, 16 Dec 2015 10:04:36 +0900 Subject: [PATCH 02/16] [waylandsrc] fills more information for MMVideoBuf Change-Id: I63959b34a776a3d2a973f50693bbf32f7ecaa6f1 --- waylandsrc/src/gstwaylandsrc.c | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/waylandsrc/src/gstwaylandsrc.c b/waylandsrc/src/gstwaylandsrc.c index e1a1e0a..e33562a 100644 --- a/waylandsrc/src/gstwaylandsrc.c +++ b/waylandsrc/src/gstwaylandsrc.c @@ -345,6 +345,16 @@ mirror_handle_dequeued (void *data, mm_video_buf->size[0] = gst_calculate_y_size(src->width, src->height); /*(src->width * src->height);*/ mm_video_buf->size[1] = gst_calculate_uv_size(src->width, src->height); /*(src->width * (src->height >> 1));*/ + GST_INFO_OBJECT (src, "Size : %d %d", mm_video_buf->size[0], mm_video_buf->size[1]); + + mm_video_buf->handle.dmabuf_fd[0] = tbm_bo_get_handle(out_buffer->bo[0], TBM_DEVICE_MM).u32; + mm_video_buf->handle.dmabuf_fd[1] = tbm_bo_get_handle(out_buffer->bo[1], TBM_DEVICE_MM).u32; + + mm_video_buf->handle.paddr[0] = (tbm_bo_map(mm_video_buf->handle.bo[0], TBM_DEVICE_CPU,TBM_OPTION_WRITE)).ptr; + mm_video_buf->handle.paddr[1] = (tbm_bo_map(mm_video_buf->handle.bo[1], TBM_DEVICE_CPU,TBM_OPTION_WRITE)).ptr; + tbm_bo_unmap (mm_video_buf->handle.bo[0]); + tbm_bo_unmap (mm_video_buf->handle.bo[1]); + mm_video_buf->width[0] = src->width; mm_video_buf->height[0] = src->height; mm_video_buf->format = MM_PIXEL_FORMAT_NV12; -- 2.7.4 From 2a32e6e673d73e68b3dc1e0cfc90e657e98a95a5 Mon Sep 17 00:00:00 2001 From: Hyunil Date: Thu, 17 Dec 2015 14:42:37 +0900 Subject: [PATCH 03/16] Disable waylandsink 1.4.1 Change-Id: I8043c94397418f3ea2147e4f44f2d04dba36d61a Signed-off-by: Hyunil --- Makefile.am | 6 +++--- packaging/gst-plugins-tizen.spec | 2 +- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/Makefile.am b/Makefile.am index d47c423..0b60630 100644 --- a/Makefile.am +++ b/Makefile.am @@ -61,9 +61,9 @@ if GST_TIZEN_USE_DRMDECRYPTOR SUBDIRS += drmdecryptor endif -if GST_TIZEN_USE_WAYLANDSINK -SUBDIRS += waylandsink -endif +#if GST_TIZEN_USE_WAYLANDSINK +#SUBDIRS += waylandsink +#endif DIST_SUBDIRS = common diff --git a/packaging/gst-plugins-tizen.spec b/packaging/gst-plugins-tizen.spec index 78c54e6..bc5a8f7 100644 --- a/packaging/gst-plugins-tizen.spec +++ b/packaging/gst-plugins-tizen.spec @@ -56,7 +56,7 @@ export CFLAGS+=" -DGST_EXT_TIME_ANALYSIS -DGST_EXT_XV_ENHANCEMENT -DGST_WLSINK_E %configure \ %if %{with x} --disable-waylandsrc\ - --disable-waylandsink\ +# --disable-waylandsink\ %else --disable-xvimagesrc\ %endif -- 2.7.4 From 27cbb50eb910c2323ff332a31901c6bacdd641d6 Mon Sep 17 00:00:00 2001 From: Eunhae Choi Date: Tue, 29 Dec 2015 22:44:02 +0900 Subject: [PATCH 04/16] wfdtsdemux: resolve svace issue Change-Id: I677614b3c25a61c7443f789e12517550336d8b60 --- wfdtsdemux/wfdtsdemux.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/wfdtsdemux/wfdtsdemux.c b/wfdtsdemux/wfdtsdemux.c index cf9cc38..f9a6a4b 100755 --- a/wfdtsdemux/wfdtsdemux.c +++ b/wfdtsdemux/wfdtsdemux.c @@ -2042,7 +2042,7 @@ gst_wfd_ts_demux_push_pending_data (GstWFDTSDemux * demux, WFDTSDemuxStream * st stream->needs_keyframe = FALSE; } else { base->seek_offset = demux->last_seek_offset - 200 * base->packetsize; - if (demux->last_seek_offset < 200 * base->packetsize) + if (demux->last_seek_offset < 200 * (guint64)base->packetsize) base->seek_offset = 0; demux->last_seek_offset = base->seek_offset; wfd_ts_packetizer_flush (base->packetizer, FALSE); -- 2.7.4 From cde58be9dadc663811e7644703abf01fbcfb4278 Mon Sep 17 00:00:00 2001 From: Gilbok Lee Date: Wed, 30 Dec 2015 09:21:08 +0900 Subject: [PATCH 05/16] Remove Apache-2.0 license in spec file Change-Id: Id798ce43ad9604962825130a5cd767d7547d8d0e Signed-off-by: Gilbok Lee --- packaging/gst-plugins-tizen.spec | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packaging/gst-plugins-tizen.spec b/packaging/gst-plugins-tizen.spec index bc5a8f7..4628f62 100644 --- a/packaging/gst-plugins-tizen.spec +++ b/packaging/gst-plugins-tizen.spec @@ -8,7 +8,7 @@ Summary: GStreamer tizen plugins (common) Release: 18 Group: Multimedia/Framework Url: http://gstreamer.freedesktop.org/ -License: LGPL-2.1+ and Apache-2.0 +License: LGPL-2.1+ Source0: %{name}-%{version}.tar.gz #BuildRequires: pkgconfig(camsrcjpegenc) -- 2.7.4 From 2c01ccfb4198e331e8904efb8636844d851df426 Mon Sep 17 00:00:00 2001 From: Jeongmo Yang Date: Tue, 5 Jan 2016 11:27:54 +0900 Subject: [PATCH 06/16] [tizenipc] Add new plugins - tizenipcsink, tizenipcsrc Change-Id: I6e3045adddfc546f52333fc83d35ea08389a2892 Signed-off-by: Jeongmo Yang --- Makefile.am | 4 + configure.ac | 14 + packaging/gst-plugins-tizen.spec | 2 +- tizenipc/Makefile.am | 1 + tizenipc/src/Makefile.am | 37 ++ tizenipc/src/gsttizenipcsink.c | 1082 ++++++++++++++++++++++++++++++++++++++ tizenipc/src/gsttizenipcsink.h | 108 ++++ tizenipc/src/gsttizenipcsrc.c | 931 ++++++++++++++++++++++++++++++++ tizenipc/src/gsttizenipcsrc.h | 102 ++++ 9 files changed, 2280 insertions(+), 1 deletion(-) create mode 100644 tizenipc/Makefile.am create mode 100644 tizenipc/src/Makefile.am create mode 100644 tizenipc/src/gsttizenipcsink.c create mode 100644 tizenipc/src/gsttizenipcsink.h create mode 100644 tizenipc/src/gsttizenipcsrc.c create mode 100644 tizenipc/src/gsttizenipcsrc.h diff --git a/Makefile.am b/Makefile.am index 0b60630..b24db2f 100644 --- a/Makefile.am +++ b/Makefile.am @@ -61,6 +61,10 @@ if GST_TIZEN_USE_DRMDECRYPTOR SUBDIRS += drmdecryptor endif +if GST_TIZEN_USE_TIZENIPC +SUBDIRS += tizenipc +endif + #if GST_TIZEN_USE_WAYLANDSINK #SUBDIRS += waylandsink #endif diff --git a/configure.ac b/configure.ac index 1425242..8508a31 100644 --- a/configure.ac +++ b/configure.ac @@ -498,6 +498,18 @@ PKG_CHECK_MODULES(WAYLAND, wayland-client >= 1.4.0 wayland-tbm-client tizen-exte AC_PATH_PROG([wayland_scanner], [wayland-scanner]) fi +dnl use tizenipc-------------------------------------------------------------------------- +AC_ARG_ENABLE(tizenipc, AC_HELP_STRING([--enable-tizenipc], [using tizenipc]), + [ + case "${enableval}" in + yes) GST_TIZEN_USE_TIZENIPC=yes ;; + no) GST_TIZEN_USE_TIZENIPC=no ;; + *) AC_MSG_ERROR(bad value ${enableval} for --enable-tizenipc) ;; + esac + ], + [GST_TIZEN_USE_TIZENIPC=yes]) +AM_CONDITIONAL(GST_TIZEN_USE_TIZENIPC, test "x$GST_TIZEN_USE_TIZENIPC" = "xyes") + AC_OUTPUT( Makefile common/Makefile @@ -530,4 +542,6 @@ drmdecryptor/Makefile drmdecryptor/src/Makefile waylandsink/Makefile waylandsink/src/Makefile +tizenipc/Makefile +tizenipc/src/Makefile ) diff --git a/packaging/gst-plugins-tizen.spec b/packaging/gst-plugins-tizen.spec index 4628f62..b75a9e3 100644 --- a/packaging/gst-plugins-tizen.spec +++ b/packaging/gst-plugins-tizen.spec @@ -5,7 +5,7 @@ Name: gst-plugins-tizen Version: 1.0.0 Summary: GStreamer tizen plugins (common) -Release: 18 +Release: 19 Group: Multimedia/Framework Url: http://gstreamer.freedesktop.org/ License: LGPL-2.1+ diff --git a/tizenipc/Makefile.am b/tizenipc/Makefile.am new file mode 100644 index 0000000..af437a6 --- /dev/null +++ b/tizenipc/Makefile.am @@ -0,0 +1 @@ +SUBDIRS = src diff --git a/tizenipc/src/Makefile.am b/tizenipc/src/Makefile.am new file mode 100644 index 0000000..c0bbd25 --- /dev/null +++ b/tizenipc/src/Makefile.am @@ -0,0 +1,37 @@ +# plugindir is set in configure + +############################################################################## +# change libgstplugin.la to something more suitable, e.g. libmysomething.la # +############################################################################## +plugin_LTLIBRARIES = libgsttizenipcsink.la libgsttizenipcsrc.la + +############################################################################## +# for the next set of variables, rename the prefix if you renamed the .la, # +# e.g. libgstplugin_la_SOURCES => libmysomething_la_SOURCES # +# libgstplugin_la_CFLAGS => libmysomething_la_CFLAGS # +# libgstplugin_la_LIBADD => libmysomething_la_LIBADD # +# libgstplugin_la_LDFLAGS => libmysomething_la_LDFLAGS # +############################################################################## + +# sources used to compile this plug-in +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_LDFLAGS = $(GST_PLUGIN_LDFLAGS) + +# sources used to compile this plug-in +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_LDFLAGS = $(GST_PLUGIN_LDFLAGS) + +# headers we need but don't want installed +noinst_HEADERS = gsttizenipcsink.h \ + gsttizenipcsrc.h + diff --git a/tizenipc/src/gsttizenipcsink.c b/tizenipc/src/gsttizenipcsink.c new file mode 100644 index 0000000..a2771e6 --- /dev/null +++ b/tizenipc/src/gsttizenipcsink.c @@ -0,0 +1,1082 @@ +/* + * GStreamer Tizen IPC sink + * + * Copyright (C) 2015 Jeongmo Yang + * + * 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. + */ + +#ifdef HAVE_CONFIG_H +#include +#endif + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include "gsttizenipcsink.h" + +#define DEFAULT_SOCKET_PATH "/tmp/tizenipc.0" +#define DEFAULT_SHM_PATH "/tizenipcshm" +#define DEFAULT_PERMISSIONS (S_IRUSR|S_IWUSR|S_IRGRP) +#define DEFAULT_BACKLOG 5 +#define CLIENT_RESPONSE_TIMEOUT (G_TIME_SPAN_MILLISECOND * 200) +#define BUFFER_WAIT_TIMEOUT (G_TIME_SPAN_MILLISECOND * 3000) + +GST_DEBUG_CATEGORY(gst_debug_tizenipc_sink); + +#define GST_CAT_DEFAULT gst_debug_tizenipc_sink + +static GstStaticPadTemplate sinktemplate = \ + GST_STATIC_PAD_TEMPLATE("sink", + GST_PAD_SINK, + GST_PAD_ALWAYS, + GST_STATIC_CAPS_ANY); + +#define gst_tizenipc_sink_parent_class parent_class +G_DEFINE_TYPE(GstTizenipcSink, gst_tizenipc_sink, GST_TYPE_BASE_SINK); + +/* signals */ +enum { + SIGNAL_CLIENT_CONNECTED, + SIGNAL_CLIENT_DISCONNECTED, + LAST_SIGNAL +}; + +/* properties */ +enum { + PROP_0, + PROP_SOCKET_PATH, + PROP_PERMISSIONS +}; + + + +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); + +static void gst_tizenipc_sink_finalize(GObject *object); +static void gst_tizenipc_sink_set_property(GObject *object, guint prop_id, + const GValue *value, GParamSpec *pspec); +static void gst_tizenipc_sink_get_property(GObject *object, guint prop_id, + GValue *value, GParamSpec *pspec); +static gboolean gst_tizenipc_sink_start(GstBaseSink *bsink); +static gboolean gst_tizenipc_sink_stop(GstBaseSink *bsink); +static GstFlowReturn gst_tizenipc_sink_render(GstBaseSink *bsink, GstBuffer *buf); +static gboolean gst_tizenipc_sink_event(GstBaseSink *bsink, GstEvent *event); +static gboolean gst_tizenipc_sink_unlock(GstBaseSink *bsink); +static gboolean gst_tizenipc_sink_unlock_stop(GstBaseSink *bsink); + +static gpointer _gst_poll_thread_func(gpointer data); + +static guint signals[LAST_SIGNAL] = {0, 0}; + + + + +static gboolean _prepare_tizenipc_sink(GstTizenipcSink *self, guint shm_size) +{ + 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) { + 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) { + GST_ERROR_OBJECT(self, "failed to create socket"); + return FALSE; + } + + flags = fcntl(self->socket_fd, F_GETFL, NULL); + if (flags < 0) { + GST_ERROR_OBJECT(self, "failed to fcntl F_GETFL"); + goto _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; + } + + memset(&addr_un, 0x0, sizeof(addr_un)); + + addr_un.sun_family = AF_UNIX; + strncpy(addr_un.sun_path, self->socket_path, sizeof(addr_un.sun_path) - 1); + + address = (struct sockaddr *)(&addr_un); + address_len = sizeof(addr_un); + + unlink(self->socket_path); + + /* bind socket */ + while (bind(self->socket_fd, address, address_len) < 0) { + if (errno != EADDRINUSE) { + GST_ERROR_OBJECT(self, "failed to bind. errno %d", errno); + goto _FAILED; + } + + if (i > 256) { + GST_ERROR_OBJECT(self, "no more free socket name"); + goto _FAILED; + } + + snprintf(addr_un.sun_path, sizeof(addr_un.sun_path), "%s.%d", self->socket_path, i); + i++; + + unlink(addr_un.sun_path); + } + + if (self->socket_path_result) { + g_free(self->socket_path_result); + self->socket_path_result = NULL; + } + + 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; + } + + 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; + } + + if (listen(self->socket_fd, DEFAULT_BACKLOG) < 0) { + GST_ERROR_OBJECT(self, "failed to listen"); + goto _FAILED; + } + + /* 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); + } while (self->shm_fd < 0 && errno == EEXIST); + + if (self->shm_fd < 0) { + GST_ERROR_OBJECT(self, "failed to open shared memory [%s], errno [%d]", shm_path, errno); + goto _FAILED; + } + + if (self->shm_path) { + g_free(self->shm_path); + self->shm_path = NULL; + } + + self->shm_path = g_strdup(shm_path); + if (self->shm_path == NULL) { + GST_ERROR_OBJECT(self, "failed to copy shared memory path"); + goto _FAILED; + } + + if (ftruncate(self->shm_fd, shm_size) < 0) { + GST_ERROR_OBJECT(self, "failed to resize shm to %d", shm_size); + goto _FAILED; + } + + self->shm_mapped_area = (gchar *)mmap(NULL, + 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; + } + + self->shm_mapped_size = shm_size; + + /* 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); + gst_poll_fd_ctl_read(self->poll, &self->pollfd, TRUE); + + self->poll_thread_run = TRUE; + self->poll_thread = g_thread_try_new("gsttizenipcsink_poll_thread", + _gst_poll_thread_func, + self, + NULL); + if (self->poll_thread == NULL) { + GST_ERROR_OBJECT(self, "failed to create thread for gst poll"); + self->poll_thread_run = FALSE; + goto _FAILED; + } + + GST_INFO_OBJECT(self, "done - shm %p", self->shm_mapped_area); + + return TRUE; + +_FAILED: + if (self->poll) { + gst_poll_free(self->poll); + self->poll = NULL; + } + + if (self->shm_fd > -1) { + close(self->shm_fd); + self->shm_fd = -1; + } + + if (self->socket_fd > -1) { + close(self->socket_fd); + self->socket_fd = -1; + } + + return FALSE; +} + + +static gboolean _add_buffer_to_list(GstTizenipcSink *self, GstBuffer *buf, int *tbm_key) +{ + int i = 0; + int j = 0; + GstTizenipcBuffer *sended_buffer = NULL; + + if (self == NULL || buf == NULL || tbm_key == NULL) { + GST_ERROR("NULL parameter %p, %p, %p", self, buf, tbm_key); + return FALSE; + } + + g_mutex_lock(&self->buffer_lock); + + sended_buffer = self->sended_buffer; + + for (i = 0 ; i < GST_TIZENIPC_BUFFER_MAX ; i++) { + /* find empty space */ + if (sended_buffer[i].gst_buf == NULL) { + self->sended_buffer_count++; + + GST_DEBUG_OBJECT(self, "insert buffer(key[0] %d) to index %d, count %d", + tbm_key[0], i, self->sended_buffer_count); + + /* ref gst buffer and set tbm key */ + gst_buffer_ref(buf); + sended_buffer[i].gst_buf = buf; + + for (j = 0 ; j < MM_VIDEO_BUFFER_PLANE_MAX ; j++) { + if (tbm_key[j] > 0) { + sended_buffer[i].tbm_key[j] = tbm_key[j]; + } else { + break; + } + } + + g_mutex_unlock(&self->buffer_lock); + + return TRUE; + } + } + + g_mutex_unlock(&self->buffer_lock); + + GST_WARNING_OBJECT(self, "should not be reached here. no space to keep buffer"); + + return FALSE; +} + + +static gboolean _remove_buffer_from_list(GstTizenipcSink *self, int *tbm_key) +{ + int i = 0; + GstTizenipcBuffer *sended_buffer = NULL; + + if (self == NULL || tbm_key == NULL) { + GST_ERROR("NULL parameter %p, %p", self, tbm_key); + return FALSE; + } + + g_mutex_lock(&self->buffer_lock); + + sended_buffer = self->sended_buffer; + + for (i = 0 ; i < GST_TIZENIPC_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]) { + /* remove buffer info and unref gst buffer */ + self->sended_buffer_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); + + if (sended_buffer[i].gst_buf) { + gst_buffer_unref(sended_buffer[i].gst_buf); + sended_buffer[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; + + g_cond_signal(&self->buffer_cond); + g_mutex_unlock(&self->buffer_lock); + + return TRUE; + } + } + + g_cond_signal(&self->buffer_cond); + g_mutex_unlock(&self->buffer_lock); + + GST_WARNING_OBJECT(self, "could not find matched buffer for tbm_key[0] %d", tbm_key[0]); + + return FALSE; +} + + + +/* ---------------------- */ +/* MAIN METHODS */ +/* ---------------------- */ + +static void gst_tizenipc_sink_init(GstTizenipcSink *self) +{ + g_mutex_init(&self->buffer_lock); + g_cond_init(&self->buffer_cond); + 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->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) { + 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"); + } + + return; +} + +static void gst_tizenipc_sink_class_init(GstTizenipcSinkClass *klass) +{ + GObjectClass *gobject_class = NULL; + GstElementClass *gstelement_class = NULL; + GstBaseSinkClass *gstbasesink_class = NULL; + GParamSpec *pspec = NULL; + + if (klass == NULL) { + GST_ERROR("NULL klass"); + return; + } + + gobject_class = (GObjectClass *)klass; + gstelement_class = (GstElementClass *)klass; + gstbasesink_class = (GstBaseSinkClass *)klass; + + parent_class = g_type_class_peek_parent(klass); + + gobject_class->finalize = gst_tizenipc_sink_finalize; + gobject_class->set_property = gst_tizenipc_sink_set_property; + gobject_class->get_property = gst_tizenipc_sink_get_property; + + gstbasesink_class->start = GST_DEBUG_FUNCPTR(gst_tizenipc_sink_start); + gstbasesink_class->stop = GST_DEBUG_FUNCPTR(gst_tizenipc_sink_stop); + gstbasesink_class->render = GST_DEBUG_FUNCPTR(gst_tizenipc_sink_render); + gstbasesink_class->event = GST_DEBUG_FUNCPTR(gst_tizenipc_sink_event); + gstbasesink_class->unlock = GST_DEBUG_FUNCPTR(gst_tizenipc_sink_unlock); + gstbasesink_class->unlock_stop = GST_DEBUG_FUNCPTR(gst_tizenipc_sink_unlock_stop); + + /* property */ + pspec = g_param_spec_string("socket-path", + "Path to the control socket", + "The path to the control socket used to handle IPC", + NULL, + G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS); + if (pspec) { + g_object_class_install_property(gobject_class, PROP_SOCKET_PATH, pspec); + } else { + GST_ERROR("failed to get pspec for \"socket-path\""); + } + + pspec = g_param_spec_uint("permissions", + "Permissions for the IPC", + "Permissions for the IPC", + 0, 07777, DEFAULT_PERMISSIONS, + G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS); + if (pspec) { + g_object_class_install_property (gobject_class, PROP_PERMISSIONS, pspec); + } else { + GST_ERROR("failed to get pspec for \"permissions\""); + } + + /* signal */ + signals[SIGNAL_CLIENT_CONNECTED] = \ + g_signal_new("client-connected", + GST_TYPE_TIZENIPC_SINK, G_SIGNAL_RUN_LAST, 0, NULL, NULL, + g_cclosure_marshal_VOID__INT, G_TYPE_NONE, 1, G_TYPE_INT); + + signals[SIGNAL_CLIENT_DISCONNECTED] = \ + g_signal_new("client-disconnected", + GST_TYPE_TIZENIPC_SINK, G_SIGNAL_RUN_LAST, 0, NULL, NULL, + g_cclosure_marshal_VOID__INT, G_TYPE_NONE, 1, G_TYPE_INT); + + gst_element_class_add_pad_template(gstelement_class, + gst_static_pad_template_get(&sinktemplate)); + + gst_element_class_set_static_metadata(gstelement_class, + "Tizen IPC Sink", + "Sink", + "Send data via IPC to the tizenipcsrc", + "Jeongmo Yang "); + + return; +} + + +static void gst_tizenipc_sink_finalize(GObject *object) +{ + GstTizenipcSink *self = NULL; + + if (object == NULL) { + GST_ERROR("NULL object"); + return; + } + + self = GST_TIZENIPC_SINK(object); + if (self == NULL) { + GST_ERROR_OBJECT(object, "failed to cast to GST_TIZENIPC_SINK with %p", object); + return; + } + + g_mutex_clear(&self->ipc_lock); + g_cond_clear(&self->ipc_cond); + 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; + } + + if (self->socket_path_result) { + 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_OBJECT_CLASS(parent_class)->finalize(object); + + return; +} + + +static void gst_tizenipc_sink_set_property(GObject *object, guint prop_id, + const GValue *value, GParamSpec *pspec) +{ + GstTizenipcSink *self = NULL; + + if (object == NULL) { + GST_ERROR("NULL object"); + return; + } + + self = GST_TIZENIPC_SINK(object); + if (self == NULL) { + GST_ERROR_OBJECT(object, "failed to cast to GST_TIZENIPC_SINK with %p", object); + return; + } + + GST_OBJECT_LOCK(object); + + switch (prop_id) { + case PROP_SOCKET_PATH: + { + gchar *temp_string = g_value_dup_string(value); + if (temp_string) { + if (self->socket_path) { + g_free(self->socket_path); + self->socket_path = NULL; + } + self->socket_path = temp_string; + } else { + GST_ERROR_OBJECT(object, "failed to copy string [%s]", g_value_get_string(value)); + } + break; + } + case PROP_PERMISSIONS: + self->permissions = g_value_get_uint(value); + break; + default: + GST_WARNING_OBJECT(object, "unknown property id [%d]", prop_id);; + break; + } + + GST_OBJECT_UNLOCK(object); + + return; +} + + +static void gst_tizenipc_sink_get_property(GObject *object, guint prop_id, + GValue *value, GParamSpec *pspec) +{ + GstTizenipcSink *self = NULL; + + if (object == NULL) { + GST_ERROR("NULL object"); + return; + } + + self = GST_TIZENIPC_SINK(object); + if (self == NULL) { + GST_ERROR_OBJECT(object, "failed to cast to GST_TIZENIPC_SINK with %p", object); + return; + } + + GST_OBJECT_LOCK(object); + + switch (prop_id) { + case PROP_SOCKET_PATH: + g_value_set_string(value, self->socket_path); + break; + case PROP_PERMISSIONS: + g_value_set_uint(value, self->permissions); + break; + default: + GST_WARNING_OBJECT(object, "unknown property id [%d]", prop_id);; + break; + } + + GST_OBJECT_UNLOCK(object); + + return; +} + + +static gboolean gst_tizenipc_sink_start(GstBaseSink *bsink) +{ + GstTizenipcSink *self = NULL; + + if (bsink == NULL) { + GST_ERROR("NULL bsink"); + return FALSE; + } + + self = GST_TIZENIPC_SINK(bsink); + if (self == NULL) { + GST_ERROR_OBJECT(bsink, "failed to cast to GST_TIZENIPC_SINK with %p", bsink); + return FALSE; + } + + /* 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); + return FALSE; + } + + /* create socket and shared memory for sending buffer */ + if (!_prepare_tizenipc_sink(self, sizeof(MMVideoBuffer) + sizeof(int)*MM_VIDEO_BUFFER_PLANE_MAX)) { + GST_ERROR_OBJECT(self, "prepare failed"); + return FALSE; + } + + return TRUE; +} + + +static gboolean gst_tizenipc_sink_stop(GstBaseSink *bsink) +{ + GstTizenipcSink *self = NULL; + gint64 wait_end_time = 0; + + if (bsink == NULL) { + GST_ERROR("NULL bsink"); + return FALSE; + } + + self = GST_TIZENIPC_SINK(bsink); + if (self == NULL) { + GST_ERROR_OBJECT(bsink, "failed to cast to GST_TIZENIPC_SINK with %p", bsink); + return FALSE; + } + + GST_INFO_OBJECT(self, "start"); + + /* stop poll thread */ + self->poll_thread_run = FALSE; + if (self->poll) { + gst_poll_set_flushing(self->poll, TRUE); + } + + if (self->poll_thread) { + GST_INFO_OBJECT(self, "join poll thread %p", self->poll_thread); + + g_thread_join(self->poll_thread); + self->poll_thread = NULL; + } else { + 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->ipc_cond, &self->ipc_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); + + 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; + } else { + GST_WARNING_OBJECT(self, "no client"); + } + + /* release shared memory */ + if (self->shm_fd >= 0) { + if (self->shm_mapped_area != MAP_FAILED) { + munmap(self->shm_mapped_area, self->shm_mapped_size); + self->shm_mapped_area = MAP_FAILED; + self->shm_mapped_size = 0; + } + + close(self->shm_fd); + self->shm_fd = -1; + + if (self->shm_path) { + shm_unlink(self->shm_path); + g_free(self->shm_path); + self->shm_path = NULL; + } + } + + /* release gst poll */ + if (self->poll) { + GST_INFO_OBJECT(self, "close gst poll %p", self->poll); + + gst_poll_free(self->poll); + self->poll = NULL; + } else { + GST_WARNING_OBJECT(self, "no gst poll"); + } + + /* close socket */ + if (self->socket_fd >= 0) { + GST_INFO_OBJECT(self, "close main socket %d", self->socket_fd); + + shutdown(self->socket_fd, SHUT_RDWR); + close(self->socket_fd); + self->socket_fd = -1; + } else { + GST_WARNING_OBJECT(self, "socket is not opened"); + } + + if (self->socket_path_result) { + unlink(self->socket_path_result); + } + + GST_INFO_OBJECT(self, "done"); + + return TRUE; +} + + +static GstFlowReturn gst_tizenipc_sink_render(GstBaseSink *bsink, GstBuffer *buf) +{ + GstTizenipcSink *self = NULL; + GstTizenipcMessage msg = {0, }; + MMVideoBuffer *mm_buf = NULL; + GstMemory *mm_buf_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) { + GST_ERROR("NULL bsink"); + return GST_FLOW_ERROR; + } + + self = GST_TIZENIPC_SINK(bsink); + if (self == NULL) { + GST_ERROR_OBJECT(bsink, "failed to cast to GST_TIZENIPC_SINK with %p", bsink); + return GST_FLOW_ERROR; + } + + if (buf == NULL) { + GST_ERROR_OBJECT(self, "NULL buffer"); + return GST_FLOW_ERROR; + } + + g_mutex_lock(&self->ipc_lock); + + if (self->client_fd < 0) { + GST_WARNING_OBJECT(self, "no client is connected"); + goto _SKIP_BUFFER; + } + + /* 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; + } + + mm_buf_memory = gst_buffer_peek_memory(buf, 1); + if (mm_buf_memory == NULL) { + GST_WARNING_OBJECT(self, "failed to peek memory 1 for %p", buf); + goto _SKIP_BUFFER; + } + + if (gst_memory_map(mm_buf_memory, &map_info, GST_MAP_READ) == FALSE) { + GST_WARNING_OBJECT(self, "failed to map memory %p", mm_buf_memory); + goto _SKIP_BUFFER; + } + + mm_buf = (MMVideoBuffer *)map_info.data; + + gst_memory_unmap(mm_buf_memory, &map_info); + + if (mm_buf == NULL) { + GST_WARNING_OBJECT(self, "NULL mm_buf"); + goto _SKIP_BUFFER; + } + + 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; + } + } + + /* 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]); + goto _SKIP_BUFFER; + } + + /* set command type and size */ + msg.type = 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 */ + if (send(self->client_fd, &msg, sizeof(GstTizenipcMessage), MSG_NOSIGNAL) != sizeof(GstTizenipcMessage)) { + GST_ERROR_OBJECT(self, "failed to send buffer to src"); + goto _SKIP_BUFFER_AFTER_ADD_TO_LIST; + } + + /* wait for client's response */ + GST_LOG_OBJECT(self, "Wait for client's response"); + + wait_end_time = g_get_monotonic_time () + CLIENT_RESPONSE_TIMEOUT; + + if (!g_cond_wait_until(&self->ipc_cond, &self->ipc_lock, wait_end_time)) { + GST_ERROR_OBJECT(self, "response wait timeout[%lld usec]", CLIENT_RESPONSE_TIMEOUT); + g_mutex_unlock(&self->ipc_lock); + goto _SKIP_BUFFER_AFTER_ADD_TO_LIST; + } else { + GST_LOG_OBJECT(self, "response received."); + } + + g_mutex_unlock(&self->ipc_lock); + + return GST_FLOW_OK; + +_SKIP_BUFFER_AFTER_ADD_TO_LIST: + _remove_buffer_from_list(self, tbm_key); + +_SKIP_BUFFER: + g_mutex_unlock(&self->ipc_lock); + + return GST_FLOW_OK; +} + + +static gboolean gst_tizenipc_sink_event(GstBaseSink *bsink, GstEvent *event) +{ + GstTizenipcSink *self = NULL; + + if (bsink == NULL) { + GST_ERROR("NULL object"); + return FALSE; + } + + self = GST_TIZENIPC_SINK(bsink); + if (self == NULL) { + GST_ERROR_OBJECT(bsink, "failed to cast to GST_TIZENIPC_SINK with %p", bsink); + return FALSE; + } + + switch (GST_EVENT_TYPE(event)) { + case GST_EVENT_EOS: + /* wait for sended buffer */ + break; + default: + break; + } + + return GST_BASE_SINK_CLASS(parent_class)->event(bsink, event); +} + + +static gboolean gst_tizenipc_sink_unlock(GstBaseSink *bsink) +{ + return TRUE; +} + + +static gboolean gst_tizenipc_sink_unlock_stop(GstBaseSink *bsink) +{ + return TRUE; +} + + +static gpointer _gst_poll_thread_func(gpointer data) +{ + GstTizenipcSink *self = NULL; + GstClockTime timeout = GST_CLOCK_TIME_NONE; + + if (data == NULL) { + GST_ERROR("NULL data"); + return NULL; + } + + self = GST_TIZENIPC_SINK(data); + if (self == NULL) { + GST_ERROR("failed to cast GST_TIZENIPC_SINK"); + return NULL; + } + + GST_INFO_OBJECT(self, "start"); + + while (self->poll_thread_run) { + if (gst_poll_wait(self->poll, timeout) < 0) { + GST_ERROR_OBJECT(self, "failed to wait gst poll. errno %d", errno); + return NULL; + } + + timeout = GST_CLOCK_TIME_NONE; + + if (self->poll_thread_run == FALSE) { + GST_INFO_OBJECT(self, "stop poll thread"); + return NULL; + } + + if (gst_poll_fd_has_closed(self->poll, &self->pollfd)) { + GST_ERROR_OBJECT(self, "failed to read from socket fd. It's closed."); + return NULL; + } + + if (gst_poll_fd_has_error(self->poll, &self->pollfd)) { + GST_ERROR_OBJECT(self, "failed to read from socket fd. It has error."); + return NULL; + } + + if (gst_poll_fd_can_read(self->poll, &self->pollfd)) { + GstTizenipcMessage msg = {0, }; + + /* connect client */ + self->client_fd = accept(self->socket_fd, NULL, NULL); + if (self->client_fd < 0) { + GST_ERROR_OBJECT(self, "can not connect client"); + continue; + } + + GST_INFO_OBJECT(self, "client accpeted : fd %d", self->client_fd); + + /* send shard memory path */ + msg.type = 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 = -1; + 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"); + close(self->client_fd); + self->client_fd = -1; + continue; + } + + GST_INFO_OBJECT(self, "send shm path done - %s", self->shm_path); + + gst_poll_fd_init(&self->client_pollfd); + self->client_pollfd.fd = self->client_fd; + gst_poll_add_fd(self->poll, &self->client_pollfd); + gst_poll_fd_ctl_read(self->poll, &self->client_pollfd, TRUE); + + g_signal_emit(self, signals[SIGNAL_CLIENT_CONNECTED], 0, self->client_pollfd.fd); + timeout = 0; + continue; + } + + if (self->client_fd > -1) { + if (gst_poll_fd_has_closed(self->poll, &self->client_pollfd)) { + GST_WARNING_OBJECT(self, "client is gone, closing"); + goto close_client; + } + + if (gst_poll_fd_has_error(self->poll, &self->client_pollfd)) { + GST_WARNING_OBJECT(self, "client fd has error, closing"); + goto close_client; + } + + /* handle message from client */ + if (gst_poll_fd_can_read(self->poll, &self->client_pollfd)) { + GstTizenipcMessage msg = {0, }; + int *tbm_key = NULL; + + if (recv(self->client_fd, &msg, sizeof(GstTizenipcMessage), MSG_DONTWAIT) != sizeof(GstTizenipcMessage)) { + GST_ERROR_OBJECT(self, "failed to receive message from client, closing"); + goto close_client; + } + + switch (msg.type) { + case TIZEN_IPC_BUFFER_NEW: + GST_WARNING_OBJECT(self, "BUFFER_NEW???"); + break; + case TIZEN_IPC_BUFFER_RECEIVED: + GST_LOG_OBJECT(self, "response message received"); + g_mutex_lock(&self->ipc_lock); + g_cond_signal(&self->ipc_cond); + g_mutex_unlock(&self->ipc_lock); + break; + case TIZEN_IPC_BUFFER_RELEASE: + tbm_key = msg.tbm_key; + + GST_LOG_OBJECT(self, "BUFFER_RELEASE : tbm key %d %d %d %d", + tbm_key[0], tbm_key[1], tbm_key[2], tbm_key[3]); + + _remove_buffer_from_list(self, tbm_key); + break; + default: + GST_WARNING_OBJECT(self, "unknown type of message : %d", msg.type); + break; + } + } + + continue; + + close_client: + g_mutex_lock(&self->ipc_lock); + + GST_INFO_OBJECT(self, "close client fd %d", self->client_fd); + + gst_poll_remove_fd(self->poll, &self->client_pollfd); + close(self->client_fd); + self->client_fd = -1; + + g_mutex_unlock(&self->ipc_lock); + + g_signal_emit(self, signals[SIGNAL_CLIENT_DISCONNECTED], 0, self->client_pollfd.fd); + + continue; + } + } + + GST_INFO_OBJECT(self, "end"); + + return NULL; +} + + +static gboolean plugin_init(GstPlugin *plugin) +{ + if (!gst_element_register(plugin, + "tizenipcsink", + GST_RANK_PRIMARY, + GST_TYPE_TIZENIPC_SINK)) { + return FALSE; + } + + GST_DEBUG_CATEGORY_INIT(gst_debug_tizenipc_sink, + "tizenipcsink", + 0, + "Tizen IPC sink element"); + + return TRUE; +} + +GST_PLUGIN_DEFINE(GST_VERSION_MAJOR, + GST_VERSION_MINOR, + tizenipcsink, + "Tizen IPC sink to deliver multimedia video buffer", + plugin_init, VERSION, GST_LICENSE, + "Samsung Electronics Co", "http://www.samsung.com") diff --git a/tizenipc/src/gsttizenipcsink.h b/tizenipc/src/gsttizenipcsink.h new file mode 100644 index 0000000..8c0ba8b --- /dev/null +++ b/tizenipc/src/gsttizenipcsink.h @@ -0,0 +1,108 @@ +/* + * GStreamer Tizen IPC sink + * + * Copyright (C) 2015 Jeongmo Yang + * + * 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_SINK_H__ +#define __GST_TIZEN_IPC_SINK_H__ + +#include +#include +#include +#include + +G_BEGIN_DECLS + +#define GST_TYPE_TIZENIPC_SINK (gst_tizenipc_sink_get_type()) +#define GST_TIZENIPC_SINK(obj) (G_TYPE_CHECK_INSTANCE_CAST((obj), GST_TYPE_TIZENIPC_SINK, GstTizenipcSink)) +#define GST_TIZENIPC_SINK_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST((klass), GST_TYPE_TIZENIPC_SINK, GstTizenipcSinkClass)) +#define GST_IS_TIZENIPC_SINK(obj) (G_TYPE_CHECK_INSTANCE_TYPE((obj),GST_TYPE_TIZENIPC_SINK)) +#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; + + /* ipc */ + int socket_fd; + int shm_fd; + GThread *poll_thread; + gboolean poll_thread_run; + gboolean is_connected; + GstPoll *poll; + GstPollFD pollfd; + int client_fd; + GstPollFD client_pollfd; + gchar *socket_path_result; + gchar *shm_path; + gchar *shm_mapped_area; + gint shm_mapped_size; + GMutex ipc_lock; + GCond ipc_cond; + + /* Property */ + gchar *socket_path; + guint permissions; + + /* buffer management */ + GstTizenipcBuffer *sended_buffer; + guint sended_buffer_count; + GMutex buffer_lock; + GCond buffer_cond; +}; + +struct _GstTizenipcSinkClass { + GstBaseSinkClass parent_class; +}; + +struct _GstTizenipcBuffer { + GstBuffer *gst_buf; + guint tbm_key[MM_VIDEO_BUFFER_PLANE_MAX]; +}; + + +enum { + TIZEN_IPC_SHM_PATH = 0, + TIZEN_IPC_BUFFER_NEW, + TIZEN_IPC_BUFFER_RECEIVED, + TIZEN_IPC_BUFFER_RELEASE +}; + +struct _GstTizenipcMessage { + int type; + union { + int size; + int tbm_key[MM_VIDEO_BUFFER_PLANE_MAX]; + }; +}; + +GType +gst_tizenipc_sink_get_type (void) + G_GNUC_CONST; + +G_END_DECLS + +#endif /* __GST_TIZEN_IPC_SINK_H__ */ diff --git a/tizenipc/src/gsttizenipcsrc.c b/tizenipc/src/gsttizenipcsrc.c new file mode 100644 index 0000000..bb3aab0 --- /dev/null +++ b/tizenipc/src/gsttizenipcsrc.c @@ -0,0 +1,931 @@ +/* + * GStreamer Tizen IPC source + * + * Copyright (C) 2015 Jeongmo Yang + * + * 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. + */ + +#ifdef HAVE_CONFIG_H +#include +#endif + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include "gsttizenipcsrc.h" + +#define DEFAULT_SOCKET_PATH "/tmp/tizenipc.0" +#define DEFAULT_SHM_PATH "/tizenipcshm" +#define DEFAULT_PERMISSIONS (S_IRUSR|S_IWUSR|S_IRGRP) +#define DEFAULT_BACKLOG 5 +#define CLIENT_RESPONSE_TIMEOUT (G_TIME_SPAN_MILLISECOND * 200) +#define BUFFER_WAIT_TIMEOUT (G_TIME_SPAN_MILLISECOND * 3000) + +GST_DEBUG_CATEGORY(gst_debug_tizenipc_src); + +#define GST_CAT_DEFAULT gst_debug_tizenipc_src + +static GstStaticPadTemplate srctemplate = \ + GST_STATIC_PAD_TEMPLATE("src", + GST_PAD_SRC, + GST_PAD_ALWAYS, + GST_STATIC_CAPS_ANY); + +#define gst_tizenipc_src_parent_class parent_class +G_DEFINE_TYPE(GstTizenipcSrc, gst_tizenipc_src, GST_TYPE_PUSH_SRC); + +/* signals */ +enum { + LAST_SIGNAL +}; + +/* properties */ +enum { + PROP_0, + PROP_SOCKET_PATH, + PROP_IS_LIVE +}; + + + +static void gst_tizenipc_src_finalize(GObject *object); +static void gst_tizenipc_src_set_property(GObject *object, guint prop_id, + const GValue *value, GParamSpec *pspec); +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 GstStateChangeReturn gst_tizenipc_src_change_state(GstElement *element, GstStateChange transition); +static void gst_tizenipc_src_buffer_finalize(GstTizenipcSrcBuffer *buffer); + + + +static gboolean _tizenipc_src_prepare_to_read(GstTizenipcSrc *self) +{ + struct sockaddr_un addr_un; + struct sockaddr *address = NULL; + socklen_t address_len = 0; + int flags = 0; + + if (self == NULL) { + GST_ERROR("NULL instance"); + return FALSE; + } + + if (self->socket_path == NULL) { + GST_ERROR_OBJECT(self, "socket path is NULL"); + return FALSE; + } + + if (self->bufmgr == NULL) { + GST_ERROR_OBJECT(self, "tbm bufmgr is not initialized"); + return FALSE; + } + + GST_INFO_OBJECT(self, "start"); + + /* socket connection */ + self->socket_fd = socket(PF_UNIX, SOCK_STREAM, 0); + if (self->socket_fd < 0) { + GST_ERROR_OBJECT(self, "failed to open socket"); + goto _PREPARE_FAILED; + } + + flags = fcntl(self->socket_fd, F_GETFL, 0); + if (flags < 0) { + GST_ERROR_OBJECT(self, "failed to fcntl F_GETFL for socket fd %d", self->socket_fd); + goto _PREPARE_FAILED; + } + + 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; + } + + addr_un.sun_family = AF_UNIX; + strncpy(addr_un.sun_path, self->socket_path, sizeof(addr_un.sun_path)-1); + + address = (struct sockaddr *)(&addr_un); + 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); + goto _PREPARE_FAILED; + } + + /* gst poll init */ + gst_poll_set_flushing(self->poll, FALSE); + gst_poll_fd_init(&self->pollfd); + self->pollfd.fd = self->socket_fd; + gst_poll_add_fd(self->poll, &self->pollfd); + gst_poll_fd_ctl_read(self->poll, &self->pollfd, TRUE); + + GST_INFO_OBJECT(self, "done - socket fd %d", self->socket_fd); + + return TRUE; + +_PREPARE_FAILED: + if (self->socket_fd >= 0) { + shutdown(self->socket_fd, SHUT_RDWR); + close(self->socket_fd); + self->socket_fd = -1; + } + + if (self->socket_path) { + unlink(self->socket_path); + } + + return FALSE; +} + + +static gboolean _tizenipc_src_stop_to_read(GstTizenipcSrc *self) +{ + gint64 wait_end_time = 0; + + if (self == NULL) { + GST_ERROR("NULL instance"); + return FALSE; + } + + GST_INFO_OBJECT(self, "start - socket fd %d, live buffer count %d", + self->socket_fd, self->live_buffer_count); + + /* wait for buffers */ + g_mutex_lock(&self->buffer_lock); + + while (self->live_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->live_buffer_count); + break; + } else { + GST_WARNING_OBJECT(self, "signal received - current count %d", + self->live_buffer_count); + } + } + + g_mutex_unlock(&self->buffer_lock); + + if (self->socket_fd >= 0) { + shutdown(self->socket_fd, SHUT_RDWR); + close(self->socket_fd); + self->socket_fd = -1; + } + + if (self->socket_path) { + unlink(self->socket_path); + } + + if (self->shm_mapped_area) { + 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; + } + + GST_INFO_OBJECT(self, "done"); + + return TRUE; +} + + +/* ---------------------- */ +/* MAIN METHODS */ +/* ---------------------- */ + +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->shm_mapped_area = MAP_FAILED; + self->bufmgr = tbm_bufmgr_init(-1); + self->socket_path = g_strdup(DEFAULT_SOCKET_PATH); + 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) { + GST_ERROR_OBJECT(self, "failed to get gst poll"); + } else { + gst_poll_fd_init(&self->pollfd); + } + + return; +} + +static void gst_tizenipc_src_class_init(GstTizenipcSrcClass *klass) +{ + GObjectClass *gobject_class = NULL; + GstElementClass *gstelement_class = NULL; + GstBaseSrcClass *gstbasesrc_class = NULL; + GstPushSrcClass *gstpush_src_class = NULL; + GParamSpec *pspec = NULL; + + gobject_class = (GObjectClass *)klass; + gstelement_class = (GstElementClass *)klass; + gstbasesrc_class = (GstBaseSrcClass *)klass; + gstpush_src_class = (GstPushSrcClass *)klass; + + gobject_class->set_property = gst_tizenipc_src_set_property; + gobject_class->get_property = gst_tizenipc_src_get_property; + gobject_class->finalize = gst_tizenipc_src_finalize; + + gstelement_class->change_state = gst_tizenipc_src_change_state; + + gstbasesrc_class->start = GST_DEBUG_FUNCPTR(gst_tizenipc_src_start); + gstbasesrc_class->stop = GST_DEBUG_FUNCPTR(gst_tizenipc_src_stop); + gstbasesrc_class->unlock = GST_DEBUG_FUNCPTR(gst_tizenipc_src_unlock); + gstbasesrc_class->unlock_stop = GST_DEBUG_FUNCPTR(gst_tizenipc_src_unlock_stop); + + gstpush_src_class->create = gst_tizenipc_src_create; + + /* property */ + pspec = g_param_spec_string("socket-path", + "Path to the control socket", + "The path to the control socket used to handle IPC", + NULL, + G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS); + if (pspec) { + g_object_class_install_property(gobject_class, PROP_SOCKET_PATH, pspec); + } else { + GST_ERROR("failed to get pspec for \"socket-path\""); + } + + pspec = 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); + if (pspec) { + g_object_class_install_property (gobject_class, PROP_IS_LIVE, pspec); + } else { + GST_ERROR("failed to get pspec for \"is-live\""); + } + + gst_element_class_add_pad_template(gstelement_class, + gst_static_pad_template_get(&srctemplate)); + + gst_element_class_set_static_metadata(gstelement_class, + "Tizen IPC Source", + "Source", + "Receive data via IPC from the tizenipcsink", + "Jeongmo Yang "); + + return; +} + + +static void gst_tizenipc_src_finalize(GObject *object) +{ + GstTizenipcSrc *self = NULL; + + if (object == NULL) { + GST_ERROR("NULL object"); + return; + } + + self = GST_TIZENIPC_SRC(object); + if (self == NULL) { + GST_ERROR_OBJECT(object, "failed to cast to GST_TIZENIPC_SRC with %p", object); + return; + } + + GST_INFO_OBJECT(self, "start"); + + 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; + } + + if (self->shm_path) { + g_free(self->shm_path); + self->shm_path = NULL; + } + + if (self->poll) { + gst_poll_free(self->poll); + self->poll = NULL; + } + + if (self->bufmgr) { + tbm_bufmgr_deinit(self->bufmgr); + self->bufmgr = NULL; + } + + GST_INFO_OBJECT(self, "done"); + + G_OBJECT_CLASS(parent_class)->finalize(object); + + return; +} + + +static void gst_tizenipc_src_set_property(GObject *object, guint prop_id, + const GValue *value, GParamSpec *pspec) +{ + GstTizenipcSrc *self = NULL; + + if (object == NULL) { + GST_ERROR("NULL object"); + return; + } + + self = GST_TIZENIPC_SRC(object); + if (self == NULL) { + GST_ERROR_OBJECT(object, "failed to cast to GST_TIZENIPC_SRC with %p", object); + return; + } + + switch (prop_id) { + case PROP_SOCKET_PATH: + { + gchar *temp_string = NULL; + + GST_OBJECT_LOCK(object); + + temp_string = g_value_dup_string(value); + if (temp_string) { + if (self->socket_path) { + g_free(self->socket_path); + self->socket_path = NULL; + } + self->socket_path = temp_string; + } else { + GST_ERROR_OBJECT(object, "failed to copy string [%s]", g_value_get_string(value)); + } + + GST_OBJECT_UNLOCK(object); + + break; + } + case PROP_IS_LIVE: + { + gboolean is_live = g_value_get_boolean(value); + GST_INFO_OBJECT(object, "set is-live %d", is_live); + gst_base_src_set_live(GST_BASE_SRC(object), is_live); + break; + } + default: + GST_WARNING_OBJECT(object, "unknown property id [%d]", prop_id);; + break; + } + + return; +} + + +static void gst_tizenipc_src_get_property(GObject *object, guint prop_id, + GValue *value, GParamSpec *pspec) +{ + GstTizenipcSrc *self = NULL; + + if (object == NULL) { + GST_ERROR("NULL object"); + return; + } + + self = GST_TIZENIPC_SRC(object); + if (self == NULL) { + GST_ERROR_OBJECT(object, "failed to cast to GST_TIZENIPC_SRC with %p", object); + return; + } + + switch (prop_id) { + case PROP_SOCKET_PATH: + GST_OBJECT_LOCK(object); + g_value_set_string(value, self->socket_path); + GST_OBJECT_UNLOCK(object); + break; + case PROP_IS_LIVE: + g_value_set_boolean(value, gst_base_src_is_live(GST_BASE_SRC(object))); + break; + default: + GST_WARNING_OBJECT(object, "unknown property id [%d]", prop_id);; + break; + } + + return; +} + + +static gboolean gst_tizenipc_src_start(GstBaseSrc *bsrc) +{ + GstTizenipcSrc *self = NULL; + gboolean is_live = FALSE; + + if (bsrc == NULL) { + GST_ERROR("NULL bsrc"); + return FALSE; + } + + self = GST_TIZENIPC_SRC(bsrc); + if (self == NULL) { + GST_ERROR_OBJECT(bsrc, "failed to cast to GST_TIZENIPC_SRC with %p", bsrc); + return FALSE; + } + + is_live = gst_base_src_is_live(bsrc); + + GST_INFO_OBJECT(bsrc, "is_live : %d", is_live); + + if (is_live) + return TRUE; + else + return _tizenipc_src_prepare_to_read(self); +} + + +static gboolean gst_tizenipc_src_stop(GstBaseSrc *bsrc) +{ + GstTizenipcSrc *self = NULL; + gboolean is_live = FALSE; + + if (bsrc == NULL) { + GST_ERROR("NULL bsrc"); + return FALSE; + } + + self = GST_TIZENIPC_SRC(bsrc); + if (self == NULL) { + GST_ERROR_OBJECT(bsrc, "failed to cast to GST_TIZENIPC_SRC with %p", bsrc); + return FALSE; + } + + is_live = gst_base_src_is_live(bsrc); + + GST_INFO_OBJECT(bsrc, "is_live : %d", is_live); + + if (is_live) + return TRUE; + else + return _tizenipc_src_stop_to_read(self); +} + + +static void gst_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; + + if (ipc_buf == NULL) { + GST_ERROR("NULL ipc_buf"); + return; + } + + self = ipc_buf->self; + mm_buf = ipc_buf->mm_buf; + + /* send message to sink for current tbm key */ + if (self->socket_fd > -1) { + send_msg.type = TIZEN_IPC_BUFFER_RELEASE; + memcpy(send_msg.tbm_key, ipc_buf->tbm_key, sizeof(int) * MM_VIDEO_BUFFER_PLANE_MAX); + send_len = send(self->socket_fd, &send_msg, sizeof(GstTizenipcMessage), MSG_NOSIGNAL); + if (send_len != sizeof(GstTizenipcMessage)) { + GST_ERROR_OBJECT(self, "failed to send BUFFER_RELEASE message"); + } + } else { + GST_ERROR_OBJECT(self, "invalid socket fd %d", self->socket_fd); + } + + 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; + } + } + + free(mm_buf); + mm_buf = NULL; + } + + /* send buffer signal */ + 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); + + self->live_buffer_count--; + g_cond_signal(&self->buffer_cond); + + g_mutex_unlock(&self->buffer_lock); + + if (self) { + gst_object_unref(self); + self = NULL; + } + + free(ipc_buf); + ipc_buf = NULL; + + return; +} + + +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; + int i = 0; + int recv_len = 0; + int send_len = 0; + + if (psrc == NULL) { + GST_ERROR("NULL psrc"); + return GST_FLOW_ERROR; + } + + self = GST_TIZENIPC_SRC(psrc); + if (self == NULL) { + GST_ERROR_OBJECT(psrc, "failed to cast to GST_TIZENIPC_SRC with %p", psrc); + return GST_FLOW_ERROR; + } + + if (outbuf == NULL) { + GST_ERROR_OBJECT(self, "NULL buffer pointer"); + return GST_FLOW_ERROR; + } + +again: + if (gst_poll_wait (self->poll, GST_CLOCK_TIME_NONE) < 0) { + if (errno == EBUSY) + return GST_FLOW_FLUSHING; + GST_ELEMENT_ERROR(self, RESOURCE, READ, ("Failed to read from sink"), + ("Poll failed on fd: %s", strerror (errno))); + return GST_FLOW_ERROR; + } + + if (gst_poll_fd_has_closed (self->poll, &self->pollfd)) { + GST_ELEMENT_ERROR(self, RESOURCE, READ, ("Failed to read from sink"), + ("Control socket has closed")); + return GST_FLOW_ERROR; + } + + if (gst_poll_fd_has_error (self->poll, &self->pollfd)) { + GST_ELEMENT_ERROR(self, RESOURCE, READ, ("Failed to read from sink"), + ("Control socket has error")); + return GST_FLOW_ERROR; + } + + if (gst_poll_fd_can_read (self->poll, &self->pollfd)) { + GST_LOG_OBJECT(self, "Reading from sink"); + + GST_OBJECT_LOCK(self); + + /* receive message from sink */ + recv_len = recv(self->socket_fd, &recv_msg, sizeof(GstTizenipcMessage), MSG_DONTWAIT); + + GST_OBJECT_UNLOCK(self); + + if (recv_len != sizeof(GstTizenipcMessage)) { + GST_ERROR_OBJECT(self, "failed to receive message from sink %d : %d", + recv_len, sizeof(GstTizenipcMessage)); + return GST_FLOW_ERROR; + } + + /* handle message */ + if (recv_msg.type == 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; + } + + 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"); + } + + /* send received message */ + send_msg.type = TIZEN_IPC_BUFFER_RECEIVED; + + GST_OBJECT_LOCK(self); + + send_len = send(self->socket_fd, &send_msg, sizeof(GstTizenipcMessage), MSG_NOSIGNAL); + + GST_OBJECT_UNLOCK(self); + + if (send_len != sizeof(GstTizenipcMessage)) { + GST_ERROR_OBJECT(self, "failed to send RECEIVED message"); + } + } else if (recv_msg.type == TIZEN_IPC_SHM_PATH) { + gchar shm_path[32] = {'\0',}; + int shm_size = sizeof(MMVideoBuffer) + (sizeof(int) * MM_VIDEO_BUFFER_PLANE_MAX); + + /* get shm path */ + recv_len = recv(self->socket_fd, shm_path, 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_INFO_OBJECT(self, "shm path from sink [%s]", shm_path); + + if (self->shm_path) { + g_free(self->shm_path); + self->shm_path = NULL; + } + + self->shm_path = g_strdup(shm_path); + if (self->shm_path == NULL) { + GST_ERROR_OBJECT(self, "failed to copy shm path string [%s]", shm_path); + return GST_FLOW_ERROR; + } + + /* open shared memory */ + self->shm_fd = shm_open(self->shm_path, O_RDONLY, shm_size); + if (self->shm_fd < 0) { + GST_ERROR_OBJECT(self, "failed to open shared memory for shm path [%s], size %d", + self->shm_path, shm_size); + return GST_FLOW_ERROR; + } + + GST_INFO_OBJECT(self, "opened shm fd %d", self->shm_fd); + + self->shm_mapped_area = mmap(NULL, + shm_size, + PROT_READ, + MAP_SHARED, + self->shm_fd, + 0); + 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; + return GST_FLOW_ERROR; + } + + self->shm_mapped_size = shm_size; + + GST_INFO_OBJECT(self, "mapped shared memory address %p, size %d", + self->shm_mapped_area, shm_size); + goto again; + } else { + GST_WARNING_OBJECT(self, "unknown message type %d", recv_msg.type); + goto again; + } + } + + if (mm_buf == NULL) { + GST_ERROR_OBJECT(self, "NULL mm_buf"); + return GST_FLOW_ERROR; + } + + /* 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; + } + + /* default memory */ + gst_memory = gst_memory_new_wrapped(0, + mm_buf->data[0], + mm_buf->size[0], + 0, + mm_buf->size[0], + NULL, + NULL); + 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; + + /* 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; + } + + gst_buffer_append_memory(gst_buf, gst_memory); + gst_memory = NULL; + + /* ipc_buf memory */ + ipc_buf = (GstTizenipcSrcBuffer *)malloc(sizeof(GstTizenipcSrcBuffer)); + if (ipc_buf == NULL) { + GST_ERROR_OBJECT(self, "failed to create GstTizenipcsrcBuffer"); + goto _CREATE_FAILED; + } + + 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; + } + + gst_buffer_append_memory(gst_buf, gst_memory); + gst_memory = NULL; + + 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); + + *outbuf = gst_buf; + + return GST_FLOW_OK; + +_CREATE_FAILED: + if (ipc_buf) { + free(ipc_buf); + ipc_buf = NULL; + } + + if (mm_buf) { + free(mm_buf); + mm_buf = NULL; + } + + if (gst_memory) { + gst_memory_unref(gst_memory); + gst_memory = NULL; + } + + if (gst_buf) { + gst_buffer_unref(gst_buf); + gst_buf = NULL; + } + + return GST_FLOW_ERROR; +} + + +static gboolean gst_tizenipc_src_unlock(GstBaseSrc *bsrc) +{ + return TRUE; +} + + +static gboolean gst_tizenipc_src_unlock_stop(GstBaseSrc *bsrc) +{ + return TRUE; +} + + +static GstStateChangeReturn gst_tizenipc_src_change_state(GstElement *element, GstStateChange transition) +{ + GstStateChangeReturn ret = GST_STATE_CHANGE_SUCCESS; + GstTizenipcSrc *self = NULL; + gboolean is_live = FALSE; + + if (element == NULL) { + GST_ERROR("NULL element"); + return FALSE; + } + + self = GST_TIZENIPC_SRC(element); + if (self == NULL) { + GST_ERROR_OBJECT(element, "failed to cast to GST_TIZENIPC_SRC with %p", element); + return FALSE; + } + + is_live = gst_base_src_is_live(GST_BASE_SRC(element)); + + GST_INFO_OBJECT(self, "transition %d - is_live %d", transition, is_live); + + switch (transition) { + case GST_STATE_CHANGE_READY_TO_PAUSED: + if (is_live) + if (!_tizenipc_src_prepare_to_read(self)) + return GST_STATE_CHANGE_FAILURE; + default: + break; + } + + ret = GST_ELEMENT_CLASS(parent_class)->change_state(element, transition); + if (ret == GST_STATE_CHANGE_FAILURE) + return ret; + + switch (transition) { + case GST_STATE_CHANGE_PAUSED_TO_READY: + if (is_live) + if (!_tizenipc_src_stop_to_read(self)) + return GST_STATE_CHANGE_FAILURE; + default: + break; + } + + return ret; +} + + +static gboolean plugin_init(GstPlugin *plugin) +{ + if (!gst_element_register(plugin, + "tizenipcsrc", + GST_RANK_PRIMARY, + GST_TYPE_TIZENIPC_SRC)) { + return FALSE; + } + + GST_DEBUG_CATEGORY_INIT(gst_debug_tizenipc_src, + "tizenipcsrc", + 0, + "Tizen IPC source element"); + + return TRUE; +} + + +GST_PLUGIN_DEFINE(GST_VERSION_MAJOR, + GST_VERSION_MINOR, + tizenipcsrc, + "Tizen IPC source to receive multimedia video buffer", + plugin_init, VERSION, GST_LICENSE, + "Samsung Electronics Co", "http://www.samsung.com") diff --git a/tizenipc/src/gsttizenipcsrc.h b/tizenipc/src/gsttizenipcsrc.h new file mode 100644 index 0000000..70b1be3 --- /dev/null +++ b/tizenipc/src/gsttizenipcsrc.h @@ -0,0 +1,102 @@ +/* + * GStreamer Tizen IPC src + * + * Copyright (C) 2015 Jeongmo Yang + * + * 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_SRC_H__ +#define __GST_TIZEN_IPC_SRC_H__ + +#include +#include +#include +#include +#include + +G_BEGIN_DECLS + +#define GST_TYPE_TIZENIPC_SRC (gst_tizenipc_src_get_type()) +#define GST_TIZENIPC_SRC(obj) (G_TYPE_CHECK_INSTANCE_CAST((obj), GST_TYPE_TIZENIPC_SRC, GstTizenipcSrc)) +#define GST_TIZENIPC_SRC_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST((klass), GST_TYPE_TIZENIPC_SRC, GstTizenipcSrcClass)) +#define GST_IS_TIZENIPC_SRC(obj) (G_TYPE_CHECK_INSTANCE_TYPE((obj),GST_TYPE_TIZENIPC_SRC)) +#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; + + /* ipc */ + int socket_fd; + int shm_fd; + GstPoll *poll; + GstPollFD pollfd; + gchar *shm_path; + gchar *shm_mapped_area; + gint shm_mapped_size; + + /* Property */ + gchar *socket_path; + + /* buffer management */ + tbm_bufmgr bufmgr; + guint live_buffer_count; + GMutex buffer_lock; + GCond buffer_cond; +}; + +struct _GstTizenipcSrcClass { + GstPushSrcClass parent_class; +}; + +struct _GstTizenipcSrcBuffer { + GstBuffer *gst_buf; + MMVideoBuffer *mm_buf; + int tbm_key[MM_VIDEO_BUFFER_PLANE_MAX]; + GstTizenipcSrc *self; +}; + + +enum { + TIZEN_IPC_SHM_PATH = 0, + TIZEN_IPC_BUFFER_NEW, + TIZEN_IPC_BUFFER_RECEIVED, + TIZEN_IPC_BUFFER_RELEASE +}; + +struct _GstTizenipcMessage { + int type; + union { + int size; + int tbm_key[MM_VIDEO_BUFFER_PLANE_MAX]; + }; +}; + +GType +gst_tizenipc_src_get_type (void) + G_GNUC_CONST; + +G_END_DECLS + +#endif /* __GST_TIZEN_IPC_SRC_H__ */ -- 2.7.4 From a9cbfa349cb47ec4e36e6d3275463643fb87393f Mon Sep 17 00:00:00 2001 From: Sangkyu Park Date: Thu, 7 Jan 2016 16:34:48 +0900 Subject: [PATCH 07/16] [wfdmanager] Add to use socket keep-alive to check timeout. Change-Id: I8052eb109915760367032ba568b22bd0954e76ec Signed-off-by: Sangkyu Park --- packaging/gst-plugins-tizen.spec | 2 +- wfdmanager/wfdbase/gstwfdbasesrc.c | 64 +++++++++++++++++++++++++++++++++++++- 2 files changed, 64 insertions(+), 2 deletions(-) diff --git a/packaging/gst-plugins-tizen.spec b/packaging/gst-plugins-tizen.spec index b75a9e3..556c2ac 100644 --- a/packaging/gst-plugins-tizen.spec +++ b/packaging/gst-plugins-tizen.spec @@ -5,7 +5,7 @@ Name: gst-plugins-tizen Version: 1.0.0 Summary: GStreamer tizen plugins (common) -Release: 19 +Release: 20 Group: Multimedia/Framework Url: http://gstreamer.freedesktop.org/ License: LGPL-2.1+ diff --git a/wfdmanager/wfdbase/gstwfdbasesrc.c b/wfdmanager/wfdbase/gstwfdbasesrc.c index ead8d81..6a87528 100755 --- a/wfdmanager/wfdbase/gstwfdbasesrc.c +++ b/wfdmanager/wfdbase/gstwfdbasesrc.c @@ -136,6 +136,10 @@ enum #define DEFAULT_PORT_RANGE NULL #define DEFAULT_USER_AGENT "TIZEN-WFD-SINK" +#define SOCKET_TCP_KEEPIDLE 5 +#define SOCKET_TCP_KEEPINTVL 2 +#define SOCKET_TCP_KEEPCNT 3 + enum { PROP_0, @@ -1138,8 +1142,64 @@ connect_retry: } } else { GST_INFO_OBJECT(src, "Connection success"); - } + gint fd = 0; + int optval = 0; + int optlen = sizeof(int); + GSocket* socket = gst_rtsp_connection_get_write_socket(info->connection); + + if(socket != NULL) { + fd = g_socket_get_fd (socket); + if(fd == 0) { + GST_INFO_OBJECT(src, "fd(write) is null"); + } + else { + optval = 1; + if(setsockopt(fd, SOL_SOCKET, SO_KEEPALIVE, (void*)&optval, sizeof(optval)) < 0) { + GST_INFO_OBJECT(src, "Error set socket SO_KEEPALIVE value to TRUE"); + } + + optval = SOCKET_TCP_KEEPIDLE; + if(setsockopt(fd, IPPROTO_TCP, 4/*TCP_KEEPIDLE*/, (void*)&optval, sizeof(optval)) < 0) { + GST_INFO_OBJECT(src, "Error set socket TCP_KEEPIDLE value"); + } + optval = SOCKET_TCP_KEEPINTVL; + if(setsockopt(fd, IPPROTO_TCP, 5/*TCP_KEEPINTVL*/, (void*)&optval, sizeof(optval)) < 0) { + GST_INFO_OBJECT(src, "Error get socket TCP_KEEPINTVL value"); + } + + optval = SOCKET_TCP_KEEPCNT; + if(setsockopt(fd, IPPROTO_TCP, 6/*TCP_KEEPCNT*/, (void*)&optval, sizeof(optval)) < 0) { + GST_INFO_OBJECT(src, "Error get socket TCP_KEEPINTVL value"); + } + + //for check + if(getsockopt(fd, SOL_SOCKET, SO_KEEPALIVE/**/, (void*)&optval, (socklen_t*)&optlen) < 0) { + GST_INFO_OBJECT(src, "Error get socket SO_KEEPALIVE option value"); + } else { + GST_INFO_OBJECT(src, "SO_KEEPALIVE : %d",optval); + } + + if(getsockopt(fd, IPPROTO_TCP, 4/*TCP_KEEPIDLE*/, (void*)&optval, (socklen_t*)&optlen) < 0) { + GST_INFO_OBJECT(src, "Error get socket TCP_KEEPIDLE option value"); + } else { + GST_INFO_OBJECT(src, "TCP_KEEPIDLE : %d",optval); + } + + if(getsockopt(fd, IPPROTO_TCP, 5/*TCP_KEEPINTVL*/, (void*)&optval, (socklen_t*)&optlen) < 0) { + GST_INFO_OBJECT(src, "Error get socket TCP_KEEPINTVL option value"); + } else { + GST_INFO_OBJECT(src, "TCP_KEEPINTVL : %d",optval); + } + + if(getsockopt(fd, IPPROTO_TCP, 6/*TCP_KEEPCNT */, (void*)&optval, (socklen_t*)&optlen) < 0) { + GST_INFO_OBJECT(src, "Error get socket TCP_KEEPCNT option value"); + } else { + GST_INFO_OBJECT(src, "TCP_KEEPCNT : %d",optval); + } + } + } + } info->connected = TRUE; } return GST_RTSP_OK; @@ -2011,6 +2071,8 @@ gst_wfd_base_src_loop (GstWFDBaseSrc * src) /* server closed the connection.*/ GST_ELEMENT_WARNING (src, RESOURCE, READ, (NULL), ("The server closed the connection.")); + gst_element_post_message (GST_ELEMENT_CAST (src), gst_message_new_element (GST_OBJECT_CAST (src), gst_structure_new ("GstWFDSrcSessionTimeout", NULL))); + goto connect_error; default: goto receive_error; -- 2.7.4 From 23e7a1d35c64be9f8ddda59620169f346a859aa2 Mon Sep 17 00:00:00 2001 From: Jeongmo Yang Date: Wed, 13 Jan 2016 17:18:39 +0900 Subject: [PATCH 08/16] [tizenipcsink] 1. Fix crash when response timeout of sended buffer, 2. Fix crash when wait for buffer in sink stop function, 3. Enhance buffer control Change-Id: I87fd3b1d4e2c4bce52752ce0dd63a67eb1635f28 Signed-off-by: Jeongmo Yang --- packaging/gst-plugins-tizen.spec | 2 +- tizenipc/src/gsttizenipcsink.c | 30 +++++++++++++++++++++++++++--- tizenipc/src/gsttizenipcsink.h | 4 +++- tizenipc/src/gsttizenipcsrc.c | 17 +++++++++++++++-- tizenipc/src/gsttizenipcsrc.h | 3 ++- 5 files changed, 48 insertions(+), 8 deletions(-) diff --git a/packaging/gst-plugins-tizen.spec b/packaging/gst-plugins-tizen.spec index 556c2ac..39d4d62 100644 --- a/packaging/gst-plugins-tizen.spec +++ b/packaging/gst-plugins-tizen.spec @@ -5,7 +5,7 @@ Name: gst-plugins-tizen Version: 1.0.0 Summary: GStreamer tizen plugins (common) -Release: 20 +Release: 21 Group: Multimedia/Framework Url: http://gstreamer.freedesktop.org/ License: LGPL-2.1+ diff --git a/tizenipc/src/gsttizenipcsink.c b/tizenipc/src/gsttizenipcsink.c index a2771e6..3b03f54 100644 --- a/tizenipc/src/gsttizenipcsink.c +++ b/tizenipc/src/gsttizenipcsink.c @@ -39,7 +39,7 @@ #define DEFAULT_SHM_PATH "/tizenipcshm" #define DEFAULT_PERMISSIONS (S_IRUSR|S_IWUSR|S_IRGRP) #define DEFAULT_BACKLOG 5 -#define CLIENT_RESPONSE_TIMEOUT (G_TIME_SPAN_MILLISECOND * 200) +#define CLIENT_RESPONSE_TIMEOUT (G_TIME_SPAN_MILLISECOND * 100) #define BUFFER_WAIT_TIMEOUT (G_TIME_SPAN_MILLISECOND * 3000) GST_DEBUG_CATEGORY(gst_debug_tizenipc_sink); @@ -669,7 +669,7 @@ static gboolean gst_tizenipc_sink_stop(GstBaseSink *bsink) while (self->sended_buffer_count > 0) { wait_end_time = g_get_monotonic_time () + BUFFER_WAIT_TIMEOUT; - if (!g_cond_wait_until(&self->ipc_cond, &self->ipc_lock, wait_end_time)) { + 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; @@ -776,6 +776,11 @@ static GstFlowReturn gst_tizenipc_sink_render(GstBaseSink *bsink, GstBuffer *buf goto _SKIP_BUFFER; } + if (self->client_closing) { + GST_WARNING_OBJECT(self, "client is closing... skip buffer"); + goto _SKIP_BUFFER; + } + /* 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)); @@ -846,10 +851,13 @@ static GstFlowReturn gst_tizenipc_sink_render(GstBaseSink *bsink, GstBuffer *buf if (!g_cond_wait_until(&self->ipc_cond, &self->ipc_lock, wait_end_time)) { GST_ERROR_OBJECT(self, "response wait timeout[%lld usec]", CLIENT_RESPONSE_TIMEOUT); - g_mutex_unlock(&self->ipc_lock); goto _SKIP_BUFFER_AFTER_ADD_TO_LIST; } else { GST_LOG_OBJECT(self, "response received."); + if (self->client_closing) { + GST_WARNING_OBJECT(self, "client is closing... skip this buffer"); + goto _SKIP_BUFFER_AFTER_ADD_TO_LIST; + } } g_mutex_unlock(&self->ipc_lock); @@ -949,13 +957,18 @@ static gpointer _gst_poll_thread_func(gpointer data) if (gst_poll_fd_can_read(self->poll, &self->pollfd)) { GstTizenipcMessage msg = {0, }; + g_mutex_lock(&self->ipc_lock); + /* connect client */ self->client_fd = accept(self->socket_fd, NULL, NULL); if (self->client_fd < 0) { GST_ERROR_OBJECT(self, "can not connect client"); + g_mutex_unlock(&self->ipc_lock); continue; } + self->client_closing = FALSE; + GST_INFO_OBJECT(self, "client accpeted : fd %d", self->client_fd); /* send shard memory path */ @@ -965,6 +978,7 @@ static gpointer _gst_poll_thread_func(gpointer data) GST_ERROR_OBJECT(self, "failed to send shard memory path 1"); close(self->client_fd); self->client_fd = -1; + g_mutex_unlock(&self->ipc_lock); continue; } @@ -972,6 +986,7 @@ static gpointer _gst_poll_thread_func(gpointer data) GST_ERROR_OBJECT(self, "failed to send shard memory path 2"); close(self->client_fd); self->client_fd = -1; + g_mutex_unlock(&self->ipc_lock); continue; } @@ -984,6 +999,8 @@ static gpointer _gst_poll_thread_func(gpointer data) g_signal_emit(self, signals[SIGNAL_CLIENT_CONNECTED], 0, self->client_pollfd.fd); timeout = 0; + + g_mutex_unlock(&self->ipc_lock); continue; } @@ -1026,6 +1043,13 @@ static gpointer _gst_poll_thread_func(gpointer data) _remove_buffer_from_list(self, tbm_key); break; + case TIZEN_IPC_CLOSE_CLIENT: + GST_LOG_OBJECT(self, "CLOSE_CLIENT message received"); + g_mutex_lock(&self->ipc_lock); + self->client_closing = TRUE; + g_cond_signal(&self->ipc_cond); + g_mutex_unlock(&self->ipc_lock); + break; default: GST_WARNING_OBJECT(self, "unknown type of message : %d", msg.type); break; diff --git a/tizenipc/src/gsttizenipcsink.h b/tizenipc/src/gsttizenipcsink.h index 8c0ba8b..5ead0f2 100644 --- a/tizenipc/src/gsttizenipcsink.h +++ b/tizenipc/src/gsttizenipcsink.h @@ -56,6 +56,7 @@ struct _GstTizenipcSink { GstPollFD pollfd; int client_fd; GstPollFD client_pollfd; + gboolean client_closing; gchar *socket_path_result; gchar *shm_path; gchar *shm_mapped_area; @@ -88,7 +89,8 @@ enum { TIZEN_IPC_SHM_PATH = 0, TIZEN_IPC_BUFFER_NEW, TIZEN_IPC_BUFFER_RECEIVED, - TIZEN_IPC_BUFFER_RELEASE + TIZEN_IPC_BUFFER_RELEASE, + TIZEN_IPC_CLOSE_CLIENT }; struct _GstTizenipcMessage { diff --git a/tizenipc/src/gsttizenipcsrc.c b/tizenipc/src/gsttizenipcsrc.c index bb3aab0..78a6075 100644 --- a/tizenipc/src/gsttizenipcsrc.c +++ b/tizenipc/src/gsttizenipcsrc.c @@ -40,7 +40,6 @@ #define DEFAULT_SHM_PATH "/tizenipcshm" #define DEFAULT_PERMISSIONS (S_IRUSR|S_IWUSR|S_IRGRP) #define DEFAULT_BACKLOG 5 -#define CLIENT_RESPONSE_TIMEOUT (G_TIME_SPAN_MILLISECOND * 200) #define BUFFER_WAIT_TIMEOUT (G_TIME_SPAN_MILLISECOND * 3000) GST_DEBUG_CATEGORY(gst_debug_tizenipc_src); @@ -166,6 +165,8 @@ _PREPARE_FAILED: static gboolean _tizenipc_src_stop_to_read(GstTizenipcSrc *self) { + int send_len = 0; + GstTizenipcMessage send_msg = {0,}; gint64 wait_end_time = 0; if (self == NULL) { @@ -194,6 +195,18 @@ static gboolean _tizenipc_src_stop_to_read(GstTizenipcSrc *self) g_mutex_unlock(&self->buffer_lock); if (self->socket_fd >= 0) { + /* send message to sink to noti client closing */ + GST_WARNING_OBJECT(self, "send CLOSE_CLIENT message to sink"); + + send_msg.type = TIZEN_IPC_CLOSE_CLIENT; + send_len = send(self->socket_fd, &send_msg, sizeof(GstTizenipcMessage), MSG_NOSIGNAL); + if (send_len != sizeof(GstTizenipcMessage)) { + GST_ERROR_OBJECT(self, "send failed : CLOSE_CLIENT"); + } + + usleep(30 * 1000); + GST_WARNING_OBJECT(self, "30 ms sleep to complete sending msg - done"); + shutdown(self->socket_fd, SHUT_RDWR); close(self->socket_fd); self->socket_fd = -1; @@ -519,7 +532,7 @@ static void gst_tizenipc_src_buffer_finalize(GstTizenipcSrcBuffer *ipc_buf) memcpy(send_msg.tbm_key, ipc_buf->tbm_key, sizeof(int) * MM_VIDEO_BUFFER_PLANE_MAX); send_len = send(self->socket_fd, &send_msg, sizeof(GstTizenipcMessage), MSG_NOSIGNAL); if (send_len != sizeof(GstTizenipcMessage)) { - GST_ERROR_OBJECT(self, "failed to send BUFFER_RELEASE message"); + GST_ERROR_OBJECT(self, "send failed : BUFFER_RELEASE key[0] %d", send_msg.tbm_key[0]); } } else { GST_ERROR_OBJECT(self, "invalid socket fd %d", self->socket_fd); diff --git a/tizenipc/src/gsttizenipcsrc.h b/tizenipc/src/gsttizenipcsrc.h index 70b1be3..c7ebfdd 100644 --- a/tizenipc/src/gsttizenipcsrc.h +++ b/tizenipc/src/gsttizenipcsrc.h @@ -82,7 +82,8 @@ enum { TIZEN_IPC_SHM_PATH = 0, TIZEN_IPC_BUFFER_NEW, TIZEN_IPC_BUFFER_RECEIVED, - TIZEN_IPC_BUFFER_RELEASE + TIZEN_IPC_BUFFER_RELEASE, + TIZEN_IPC_CLOSE_CLIENT }; struct _GstTizenipcMessage { -- 2.7.4 From 98b600f00906ba61dba949898463bd30e64c7a8d Mon Sep 17 00:00:00 2001 From: Jeongmo Yang Date: Wed, 20 Jan 2016 11:03:52 +0900 Subject: [PATCH 09/16] [tizenipc] Support normal format - NV12, NV21, I420, YV12, YUYV, UYVY Change-Id: Id8cf65fe740880a677d08aa935f4f03f31662ffa Signed-off-by: Jeongmo Yang --- packaging/gst-plugins-tizen.spec | 2 +- tizenipc/src/gsttizenipcsink.c | 262 ++++++++++++++++++++++++++++++--------- tizenipc/src/gsttizenipcsink.h | 20 ++- tizenipc/src/gsttizenipcsrc.c | 201 ++++++++++++++++-------------- tizenipc/src/gsttizenipcsrc.h | 17 ++- 5 files changed, 347 insertions(+), 155 deletions(-) diff --git a/packaging/gst-plugins-tizen.spec b/packaging/gst-plugins-tizen.spec index 39d4d62..9776b98 100644 --- a/packaging/gst-plugins-tizen.spec +++ b/packaging/gst-plugins-tizen.spec @@ -5,7 +5,7 @@ Name: gst-plugins-tizen Version: 1.0.0 Summary: GStreamer tizen plugins (common) -Release: 21 +Release: 22 Group: Multimedia/Framework Url: http://gstreamer.freedesktop.org/ License: LGPL-2.1+ diff --git a/tizenipc/src/gsttizenipcsink.c b/tizenipc/src/gsttizenipcsink.c index 3b03f54..59de30e 100644 --- a/tizenipc/src/gsttizenipcsink.c +++ b/tizenipc/src/gsttizenipcsink.c @@ -39,8 +39,9 @@ #define DEFAULT_SHM_PATH "/tizenipcshm" #define DEFAULT_PERMISSIONS (S_IRUSR|S_IWUSR|S_IRGRP) #define DEFAULT_BACKLOG 5 -#define CLIENT_RESPONSE_TIMEOUT (G_TIME_SPAN_MILLISECOND * 100) -#define BUFFER_WAIT_TIMEOUT (G_TIME_SPAN_MILLISECOND * 3000) +#define CLIENT_RESPONSE_TIMEOUT_NORMAL (G_TIME_SPAN_SECOND) +#define CLIENT_RESPONSE_TIMEOUT_ZERO_COPY (G_TIME_SPAN_MILLISECOND * 100) +#define BUFFER_WAIT_TIMEOUT (G_TIME_SPAN_MILLISECOND * 3000) GST_DEBUG_CATEGORY(gst_debug_tizenipc_sink); @@ -86,6 +87,8 @@ static GstFlowReturn gst_tizenipc_sink_render(GstBaseSink *bsink, GstBuffer *buf static gboolean gst_tizenipc_sink_event(GstBaseSink *bsink, GstEvent *event); static gboolean gst_tizenipc_sink_unlock(GstBaseSink *bsink); static gboolean gst_tizenipc_sink_unlock_stop(GstBaseSink *bsink); +static gboolean gst_tizenipc_sink_set_caps(GstBaseSink *bsink, GstCaps *caps); +static GstCaps *gst_tizenipc_sink_get_caps(GstBaseSink *bsink, GstCaps *filter); static gpointer _gst_poll_thread_func(gpointer data); @@ -420,6 +423,8 @@ static void gst_tizenipc_sink_class_init(GstTizenipcSinkClass *klass) gobject_class->set_property = gst_tizenipc_sink_set_property; gobject_class->get_property = gst_tizenipc_sink_get_property; + gstbasesink_class->get_caps = GST_DEBUG_FUNCPTR(gst_tizenipc_sink_get_caps); + gstbasesink_class->set_caps = GST_DEBUG_FUNCPTR(gst_tizenipc_sink_set_caps); gstbasesink_class->start = GST_DEBUG_FUNCPTR(gst_tizenipc_sink_start); gstbasesink_class->stop = GST_DEBUG_FUNCPTR(gst_tizenipc_sink_stop); gstbasesink_class->render = GST_DEBUG_FUNCPTR(gst_tizenipc_sink_render); @@ -621,11 +626,7 @@ static gboolean gst_tizenipc_sink_start(GstBaseSink *bsink) return FALSE; } - /* create socket and shared memory for sending buffer */ - if (!_prepare_tizenipc_sink(self, sizeof(MMVideoBuffer) + sizeof(int)*MM_VIDEO_BUFFER_PLANE_MAX)) { - GST_ERROR_OBJECT(self, "prepare failed"); - return FALSE; - } + GST_INFO_OBJECT(self, "start"); return TRUE; } @@ -747,7 +748,7 @@ static GstFlowReturn gst_tizenipc_sink_render(GstBaseSink *bsink, GstBuffer *buf GstTizenipcSink *self = NULL; GstTizenipcMessage msg = {0, }; MMVideoBuffer *mm_buf = NULL; - GstMemory *mm_buf_memory = 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, }; @@ -781,62 +782,87 @@ static GstFlowReturn gst_tizenipc_sink_render(GstBaseSink *bsink, GstBuffer *buf goto _SKIP_BUFFER; } - /* 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; - } + 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; + } - mm_buf_memory = gst_buffer_peek_memory(buf, 1); - if (mm_buf_memory == NULL) { - GST_WARNING_OBJECT(self, "failed to peek memory 1 for %p", buf); - goto _SKIP_BUFFER; - } + if (gst_memory_map(memory, &map_info, GST_MAP_READ) == FALSE) { + GST_WARNING_OBJECT(self, "failed to map memory %p", memory); + goto _SKIP_BUFFER; + } - if (gst_memory_map(mm_buf_memory, &map_info, GST_MAP_READ) == FALSE) { - GST_WARNING_OBJECT(self, "failed to map memory %p", mm_buf_memory); - goto _SKIP_BUFFER; - } + GST_INFO_OBJECT(self, "map data %p, map size %d", map_info.data, map_info.size); - mm_buf = (MMVideoBuffer *)map_info.data; + memcpy(self->shm_mapped_area, map_info.data, map_info.size); - gst_memory_unmap(mm_buf_memory, &map_info); + GST_INFO_OBJECT(self, "copy done"); - if (mm_buf == NULL) { - GST_WARNING_OBJECT(self, "NULL mm_buf"); - goto _SKIP_BUFFER; - } + gst_memory_unmap(memory, &map_info); + + /* set command type and size */ + 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; + } + + 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; + } + + if (gst_memory_map(memory, &map_info, GST_MAP_READ) == FALSE) { + GST_WARNING_OBJECT(self, "failed to map memory %p", memory); + goto _SKIP_BUFFER; + } + + mm_buf = (MMVideoBuffer *)map_info.data; - GST_LOG_OBJECT(self, "MMVideoBuffer info - %p, num handle %d", - mm_buf, mm_buf->handle_num); + gst_memory_unmap(memory, &map_info); + + if (mm_buf == NULL) { + GST_WARNING_OBJECT(self, "NULL mm_buf"); + goto _SKIP_BUFFER; + } - /* 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; + 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; } - } else { - break; } - } - /* 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]); - 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]); + goto _SKIP_BUFFER; + } - /* set command type and size */ - msg.type = TIZEN_IPC_BUFFER_NEW; - msg.size = sizeof(MMVideoBuffer) + sizeof(tbm_key); + /* 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)); + /* 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 */ if (send(self->client_fd, &msg, sizeof(GstTizenipcMessage), MSG_NOSIGNAL) != sizeof(GstTizenipcMessage)) { @@ -847,10 +873,12 @@ static GstFlowReturn gst_tizenipc_sink_render(GstBaseSink *bsink, GstBuffer *buf /* wait for client's response */ GST_LOG_OBJECT(self, "Wait for client's response"); - wait_end_time = g_get_monotonic_time () + CLIENT_RESPONSE_TIMEOUT; + wait_end_time = g_get_monotonic_time () + \ + (self->is_normal_format ? CLIENT_RESPONSE_TIMEOUT_NORMAL : CLIENT_RESPONSE_TIMEOUT_ZERO_COPY); if (!g_cond_wait_until(&self->ipc_cond, &self->ipc_lock, wait_end_time)) { - GST_ERROR_OBJECT(self, "response wait timeout[%lld usec]", CLIENT_RESPONSE_TIMEOUT); + GST_ERROR_OBJECT(self, "response wait timeout[%lld usec]", + self->is_normal_format ? CLIENT_RESPONSE_TIMEOUT_NORMAL : CLIENT_RESPONSE_TIMEOUT_ZERO_COPY); goto _SKIP_BUFFER_AFTER_ADD_TO_LIST; } else { GST_LOG_OBJECT(self, "response received."); @@ -865,7 +893,8 @@ static GstFlowReturn gst_tizenipc_sink_render(GstBaseSink *bsink, GstBuffer *buf return GST_FLOW_OK; _SKIP_BUFFER_AFTER_ADD_TO_LIST: - _remove_buffer_from_list(self, tbm_key); + if (!self->is_normal_format) + _remove_buffer_from_list(self, tbm_key); _SKIP_BUFFER: g_mutex_unlock(&self->ipc_lock); @@ -913,6 +942,99 @@ 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"); + return FALSE; + } + + self = GST_TIZENIPC_SINK(bsink); + if (self == NULL) { + GST_ERROR_OBJECT(bsink, "failed to cast to GST_TIZENIPC_SINK with %p", bsink); + return FALSE; + } + + 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); + return FALSE; + } + + if (!gst_structure_has_name(structure, "video/x-raw")) { + GST_ERROR_OBJECT(self, "not supported caps [%"GST_PTR_FORMAT"]", caps); + 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; + } + + 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 (!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; + } + + GST_INFO_OBJECT(self, "format %s, size %dx%d, shm size %d", + self->format_string, self->width, self->height, self->shm_size); + + /* create socket and shared memory for sending buffer */ + if (!_prepare_tizenipc_sink(self, self->shm_size)) { + GST_ERROR_OBJECT(self, "prepare failed"); + return FALSE; + } + + return TRUE; +} + + +static GstCaps *gst_tizenipc_sink_get_caps(GstBaseSink *bsink, GstCaps *filter) +{ + GstTizenipcSink *self = NULL; + + if (bsink == NULL) { + GST_ERROR("NULL object"); + return NULL; + } + + self = GST_TIZENIPC_SINK(bsink); + if (self == NULL) { + GST_ERROR_OBJECT(bsink, "failed to cast to GST_TIZENIPC_SINK with %p", bsink); + return NULL; + } + + GST_INFO_OBJECT(self, "start"); + + return NULL; +} + + static gpointer _gst_poll_thread_func(gpointer data) { GstTizenipcSink *self = NULL; @@ -971,8 +1093,19 @@ 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; + } + /* send shard memory path */ - msg.type = TIZEN_IPC_SHM_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"); @@ -992,6 +1125,19 @@ static gpointer _gst_poll_thread_func(gpointer data) 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"); + close(self->client_fd); + self->client_fd = -1; + g_mutex_unlock(&self->ipc_lock); + continue; + } + + GST_INFO_OBJECT(self, "send buffer type done - %d", msg.type); + gst_poll_fd_init(&self->client_pollfd); self->client_pollfd.fd = self->client_fd; gst_poll_add_fd(self->poll, &self->client_pollfd); @@ -1025,7 +1171,7 @@ static gpointer _gst_poll_thread_func(gpointer data) goto close_client; } - switch (msg.type) { + switch (msg.id) { case TIZEN_IPC_BUFFER_NEW: GST_WARNING_OBJECT(self, "BUFFER_NEW???"); break; @@ -1051,7 +1197,7 @@ static gpointer _gst_poll_thread_func(gpointer data) g_mutex_unlock(&self->ipc_lock); break; default: - GST_WARNING_OBJECT(self, "unknown type of message : %d", msg.type); + GST_WARNING_OBJECT(self, "unknown message : id %d", msg.id); break; } } diff --git a/tizenipc/src/gsttizenipcsink.h b/tizenipc/src/gsttizenipcsink.h index 5ead0f2..cd329e0 100644 --- a/tizenipc/src/gsttizenipcsink.h +++ b/tizenipc/src/gsttizenipcsink.h @@ -46,6 +46,11 @@ typedef struct _GstTizenipcMessage GstTizenipcMessage; struct _GstTizenipcSink { GstBaseSink parent; + const gchar *format_string; + gint width; + gint height; + gboolean is_normal_format; + /* ipc */ int socket_fd; int shm_fd; @@ -61,6 +66,7 @@ struct _GstTizenipcSink { gchar *shm_path; gchar *shm_mapped_area; gint shm_mapped_size; + gint shm_size; GMutex ipc_lock; GCond ipc_cond; @@ -85,17 +91,25 @@ struct _GstTizenipcBuffer { }; -enum { +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 { - int type; + TizenIPCID id; union { + BufferType type; int size; int tbm_key[MM_VIDEO_BUFFER_PLANE_MAX]; }; diff --git a/tizenipc/src/gsttizenipcsrc.c b/tizenipc/src/gsttizenipcsrc.c index 78a6075..6a2a7b3 100644 --- a/tizenipc/src/gsttizenipcsrc.c +++ b/tizenipc/src/gsttizenipcsrc.c @@ -198,7 +198,7 @@ static gboolean _tizenipc_src_stop_to_read(GstTizenipcSrc *self) /* send message to sink to noti client closing */ GST_WARNING_OBJECT(self, "send CLOSE_CLIENT message to sink"); - send_msg.type = TIZEN_IPC_CLOSE_CLIENT; + send_msg.id = TIZEN_IPC_CLOSE_CLIENT; send_len = send(self->socket_fd, &send_msg, sizeof(GstTizenipcMessage), MSG_NOSIGNAL); if (send_len != sizeof(GstTizenipcMessage)) { GST_ERROR_OBJECT(self, "send failed : CLOSE_CLIENT"); @@ -528,7 +528,7 @@ static void gst_tizenipc_src_buffer_finalize(GstTizenipcSrcBuffer *ipc_buf) /* send message to sink for current tbm key */ if (self->socket_fd > -1) { - send_msg.type = TIZEN_IPC_BUFFER_RELEASE; + send_msg.id = TIZEN_IPC_BUFFER_RELEASE; memcpy(send_msg.tbm_key, ipc_buf->tbm_key, sizeof(int) * MM_VIDEO_BUFFER_PLANE_MAX); send_len = send(self->socket_fd, &send_msg, sizeof(GstTizenipcMessage), MSG_NOSIGNAL); if (send_len != sizeof(GstTizenipcMessage)) { @@ -584,6 +584,7 @@ static GstFlowReturn gst_tizenipc_src_create(GstPushSrc *psrc, GstBuffer **outbu 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; @@ -642,49 +643,58 @@ again: } /* handle message */ - if (recv_msg.type == TIZEN_IPC_BUFFER_NEW) { + 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; } - 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]); + 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; } - mm_buf->data[i] = bo_handle.ptr; - } else { - break; } + } else { + GST_ERROR_OBJECT(self, "failed to alloc MMVideoBuffer"); } } else { - GST_ERROR_OBJECT(self, "failed to alloc MMVideoBuffer"); + 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); + } } /* send received message */ - send_msg.type = TIZEN_IPC_BUFFER_RECEIVED; + send_msg.id = TIZEN_IPC_BUFFER_RECEIVED; GST_OBJECT_LOCK(self); @@ -695,9 +705,8 @@ again: if (send_len != sizeof(GstTizenipcMessage)) { GST_ERROR_OBJECT(self, "failed to send RECEIVED message"); } - } else if (recv_msg.type == TIZEN_IPC_SHM_PATH) { + } else if (recv_msg.id == TIZEN_IPC_SHM_PATH) { gchar shm_path[32] = {'\0',}; - int shm_size = sizeof(MMVideoBuffer) + (sizeof(int) * MM_VIDEO_BUFFER_PLANE_MAX); /* get shm path */ recv_len = recv(self->socket_fd, shm_path, recv_msg.size, 0); @@ -721,17 +730,17 @@ again: } /* open shared memory */ - self->shm_fd = shm_open(self->shm_path, O_RDONLY, shm_size); + self->shm_fd = shm_open(self->shm_path, O_RDONLY, self->shm_size); if (self->shm_fd < 0) { GST_ERROR_OBJECT(self, "failed to open shared memory for shm path [%s], size %d", - self->shm_path, shm_size); + self->shm_path, self->shm_size); return GST_FLOW_ERROR; } GST_INFO_OBJECT(self, "opened shm fd %d", self->shm_fd); self->shm_mapped_area = mmap(NULL, - shm_size, + self->shm_size, PROT_READ, MAP_SHARED, self->shm_fd, @@ -743,19 +752,27 @@ again: return GST_FLOW_ERROR; } - self->shm_mapped_size = shm_size; + self->shm_mapped_size = self->shm_size; GST_INFO_OBJECT(self, "mapped shared memory address %p, size %d", - self->shm_mapped_area, shm_size); + self->shm_mapped_area, self->shm_size); + goto again; + } else if (recv_msg.id == TIZEN_IPC_SHM_SIZE) { + self->shm_size = recv_msg.size; + GST_INFO_OBJECT(self, "shared memory size %d", self->shm_size); + goto again; + } else if (recv_msg.id == TIZEN_IPC_BUFFER_TYPE) { + 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 type %d", recv_msg.type); + GST_WARNING_OBJECT(self, "unknown message : id %d", recv_msg.id); goto again; } } - if (mm_buf == NULL) { - GST_ERROR_OBJECT(self, "NULL mm_buf"); + if (mm_buf == NULL && normal_buffer_data == NULL) { + GST_ERROR_OBJECT(self, "All buffers are NULL"); return GST_FLOW_ERROR; } @@ -767,13 +784,15 @@ again: } /* default memory */ - gst_memory = gst_memory_new_wrapped(0, - mm_buf->data[0], - mm_buf->size[0], - 0, - mm_buf->size[0], - NULL, - NULL); + 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; @@ -782,53 +801,50 @@ again: gst_buffer_append_memory(gst_buf, gst_memory); gst_memory = NULL; - /* 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; - } - - 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; + } - /* ipc_buf memory */ - ipc_buf = (GstTizenipcSrcBuffer *)malloc(sizeof(GstTizenipcSrcBuffer)); - if (ipc_buf == NULL) { - GST_ERROR_OBJECT(self, "failed to create GstTizenipcsrcBuffer"); - goto _CREATE_FAILED; - } + gst_buffer_append_memory(gst_buf, gst_memory); + gst_memory = NULL; - 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); + /* ipc_buf memory */ + ipc_buf = (GstTizenipcSrcBuffer *)malloc(sizeof(GstTizenipcSrcBuffer)); + if (ipc_buf == NULL) { + GST_ERROR_OBJECT(self, "failed to create GstTizenipcsrcBuffer"); + goto _CREATE_FAILED; + } - 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; - } + 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; + } - gst_buffer_append_memory(gst_buf, gst_memory); - gst_memory = NULL; + gst_buffer_append_memory(gst_buf, gst_memory); + gst_memory = NULL; - 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); + 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); + } *outbuf = gst_buf; @@ -855,6 +871,11 @@ _CREATE_FAILED: gst_buf = NULL; } + if (normal_buffer_data) { + free(normal_buffer_data); + normal_buffer_data = NULL; + } + return GST_FLOW_ERROR; } diff --git a/tizenipc/src/gsttizenipcsrc.h b/tizenipc/src/gsttizenipcsrc.h index c7ebfdd..80c976c 100644 --- a/tizenipc/src/gsttizenipcsrc.h +++ b/tizenipc/src/gsttizenipcsrc.h @@ -47,6 +47,8 @@ typedef struct _GstTizenipcMessage GstTizenipcMessage; struct _GstTizenipcSrc { GstPushSrc parent; + gboolean is_normal_format; + /* ipc */ int socket_fd; int shm_fd; @@ -55,6 +57,7 @@ struct _GstTizenipcSrc { gchar *shm_path; gchar *shm_mapped_area; gint shm_mapped_size; + gint shm_size; /* Property */ gchar *socket_path; @@ -78,17 +81,25 @@ struct _GstTizenipcSrcBuffer { }; -enum { +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 { - int type; + TizenIPCID id; union { + BufferType type; int size; int tbm_key[MM_VIDEO_BUFFER_PLANE_MAX]; }; -- 2.7.4 From e51eb693ea94e839f8a51455e73fd8b82cbd2890 Mon Sep 17 00:00:00 2001 From: Hyunjun Ko Date: Thu, 28 Jan 2016 18:30:29 +0900 Subject: [PATCH 10/16] [waylandsrc] set new value for timeout on poll Change-Id: I2410db8911704c0ba52ba73312aa66580cbe3c70 --- waylandsrc/src/gstwaylandsrc.c | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/waylandsrc/src/gstwaylandsrc.c b/waylandsrc/src/gstwaylandsrc.c index e33562a..761636f 100644 --- a/waylandsrc/src/gstwaylandsrc.c +++ b/waylandsrc/src/gstwaylandsrc.c @@ -750,10 +750,8 @@ gst_wayland_src_capture_thread (GstWaylandSrc * src) pfd.events = POLLIN; /* thread loop */ - timeout = (src->format == FOURCC_NV12) ? -1 : 5; + timeout = 5; while (!src->thread_return) { - /* Workaround fix for blocking issue when getting ARGB */ - while (wl_display_prepare_read_queue (src->display, src->queue) != 0) wl_display_dispatch_queue_pending (src->display, src->queue); -- 2.7.4 From cbf021e61360d071f52c16cc32460660e695e1f8 Mon Sep 17 00:00:00 2001 From: Eunhae Choi Date: Thu, 3 Mar 2016 15:48:47 +0900 Subject: [PATCH 11/16] [pdpushsrc] fix svace issue Change-Id: I6445f35c60017ca782240cd3c381c02fdfd10d60 Signed-off-by: Eunhae Choi --- pdpushsrc/src/gstpdpushsrc.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pdpushsrc/src/gstpdpushsrc.c b/pdpushsrc/src/gstpdpushsrc.c index 064a311..c4c5714 100644 --- a/pdpushsrc/src/gstpdpushsrc.c +++ b/pdpushsrc/src/gstpdpushsrc.c @@ -377,7 +377,7 @@ gst_pd_pushsrc_create_read (GstBaseSrc * basesrc, guint64 offset, guint length, if (fstat (src->fd, &stat_results) < 0) goto could_not_stat; - avail_size = stat_results.st_size; + avail_size = (guint64)stat_results.st_size; GST_LOG_OBJECT (src, "Available data size in file = %"G_GUINT64_FORMAT, avail_size); -- 2.7.4 From 49211ea9e1a813718285c28d5fdb76e7f7ecce96 Mon Sep 17 00:00:00 2001 From: Eunhae Choi Date: Wed, 16 Mar 2016 22:42:07 +0900 Subject: [PATCH 12/16] fix build warning Change-Id: I4a4c2405fe9e302ea1f57e6e8d9808a8bf851eff Signed-off-by: Eunhae Choi --- audioeq/src/gstaudioeq.c | 20 +++++++++++--------- audioeq/src/gstaudioeq.h | 2 +- audiotp/src/gstaudiotp.c | 3 ++- drmsrc/src/gstdrmsrc.c | 4 +++- pdpushsrc/src/gstpdpushsrc.c | 9 +++------ toggle/src/gsttoggle.c | 18 +++++++++--------- 6 files changed, 29 insertions(+), 27 deletions(-) diff --git a/audioeq/src/gstaudioeq.c b/audioeq/src/gstaudioeq.c index 3fe2751..3cbe7c0 100644 --- a/audioeq/src/gstaudioeq.c +++ b/audioeq/src/gstaudioeq.c @@ -112,9 +112,6 @@ static void gst_iir_equalizer_child_proxy_interface_init (gpointer g_iface, static void gst_iir_equalizer_finalize (GObject * object); -static gboolean gst_iir_equalizer_setup (GstAudioFilter * filter, - GstAudioRingBufferSpec * fmt); - G_DEFINE_TYPE_WITH_CODE(Gstaudioeq, gst_audioeq, GST_TYPE_BASE_TRANSFORM, G_IMPLEMENT_INTERFACE(GST_TYPE_CHILD_PROXY, gst_iir_equalizer_child_proxy_interface_init)); @@ -157,12 +154,14 @@ gst_audioeq_change_state (GstElement * element, GstStateChange transition) return ret; } +#if 0 static void gst_audioeq_base_init (gpointer gclass) { GST_DEBUG ("gst_audioeq_base_init"); } +#endif static void gst_audioeq_class_init (GstaudioeqClass * klass) @@ -230,7 +229,8 @@ gst_audioeq_init (Gstaudioeq * audioeq) audioeq->filter_action = DEFAULT_FILTER_ACTION; memset(audioeq->custom_eq, 0x00, sizeof(gint) * CUSTOM_EQ_BAND_MAX); audioeq->need_update_filter = TRUE; - audioeq->equ.bands_lock = g_mutex_new (); + + g_mutex_init(&audioeq->equ.bands_lock); audioeq->equ.need_new_coefficients = TRUE; gst_iir_equalizer_compute_frequencies (audioeq, DEFAULT_CUSTOM_EQ_NUM); } @@ -254,13 +254,13 @@ gst_iir_equalizer_finalize (GObject * object) g_free (equ->bands); g_free (equ->history); - g_mutex_free (equ->bands_lock); + g_mutex_clear (&equ->bands_lock); G_OBJECT_CLASS (gst_audioeq_parent_class)->finalize (object); } -#define BANDS_LOCK(equ) g_mutex_lock(equ->bands_lock) -#define BANDS_UNLOCK(equ) g_mutex_unlock(equ->bands_lock) +#define BANDS_LOCK(equ) g_mutex_lock(&equ->bands_lock) +#define BANDS_UNLOCK(equ) g_mutex_unlock(&equ->bands_lock) /* child object */ @@ -564,7 +564,8 @@ static void gst_iir_equalizer_init (GstIirEqualizer * eq, GstIirEqualizerClass * g_class) { GST_DEBUG ("gst_iir_equalizer_init"); - eq->bands_lock = g_mutex_new (); + + g_mutex_init(&eq->bands_lock); eq->need_new_coefficients = TRUE; } @@ -1238,6 +1239,7 @@ GST_DEBUG ("gst_audioeq_get_property"); } } +#if 0 static gboolean gst_iir_equalizer_setup (GstAudioFilter * audio, GstAudioRingBufferSpec * fmt) { @@ -1270,7 +1272,7 @@ GST_DEBUG ("gst_iir_equalizer_setup"); alloc_history (equ); return TRUE; } - +#endif static gboolean plugin_init (GstPlugin * plugin) diff --git a/audioeq/src/gstaudioeq.h b/audioeq/src/gstaudioeq.h index 2b698e0..310262b 100644 --- a/audioeq/src/gstaudioeq.h +++ b/audioeq/src/gstaudioeq.h @@ -75,7 +75,7 @@ struct _GstIirEqualizer /*< private >*/ - GMutex *bands_lock; + GMutex bands_lock; GstIirEqualizerBand **bands; /* properties */ diff --git a/audiotp/src/gstaudiotp.c b/audiotp/src/gstaudiotp.c index c5b3879..ac05aec 100644 --- a/audiotp/src/gstaudiotp.c +++ b/audiotp/src/gstaudiotp.c @@ -78,6 +78,7 @@ static GstFlowReturn gst_audiotp_push_silent_frame (Gstaudiotp *audiotp, GstBuff // Gstreamer Base Functions // //////////////////////////////////////////////////////// +#if 0 /** ** ** Description: The element details and pad templates are registered with the plugin @@ -91,7 +92,7 @@ static void gst_audiotp_base_init(gpointer klass) { } - +#endif /** ** diff --git a/drmsrc/src/gstdrmsrc.c b/drmsrc/src/gstdrmsrc.c index 17a462e..51a785b 100755 --- a/drmsrc/src/gstdrmsrc.c +++ b/drmsrc/src/gstdrmsrc.c @@ -54,6 +54,7 @@ static void gst_drm_src_uri_handler_init (gpointer g_iface, gpointer iface_data) G_DEFINE_TYPE_WITH_CODE (GstDrmSrc, gst_drm_src, GST_TYPE_BASE_SRC, G_IMPLEMENT_INTERFACE(GST_TYPE_URI_HANDLER, gst_drm_src_uri_handler_init)); +#if 0 /** * This function does the following: * 1. Sets the class details @@ -66,6 +67,8 @@ G_DEFINE_TYPE_WITH_CODE (GstDrmSrc, gst_drm_src, GST_TYPE_BASE_SRC, static void gst_drm_src_base_init (gpointer g_class) { } +#endif + /** * This function does the following: * 1. Installs the properties @@ -366,7 +369,6 @@ static gboolean gst_drm_src_get_size (GstBaseSrc * basesrc, guint64 * size) { struct stat stat_results; GstDrmSrc *src = GST_DRM_SRC (basesrc); - unsigned int offset; // 1. Gets the filesize for drm file by using seek oprations diff --git a/pdpushsrc/src/gstpdpushsrc.c b/pdpushsrc/src/gstpdpushsrc.c index c4c5714..c8a7b86 100644 --- a/pdpushsrc/src/gstpdpushsrc.c +++ b/pdpushsrc/src/gstpdpushsrc.c @@ -118,7 +118,7 @@ static gboolean gst_pd_pushsrc_checkgetrange (GstPad * pad); G_DEFINE_TYPE_WITH_CODE (GstPDPushSrc, gst_pd_pushsrc, GST_TYPE_BASE_SRC, G_IMPLEMENT_INTERFACE(GST_TYPE_URI_HANDLER, gst_pd_pushsrc_uri_handler_init)); - +#if 0 static void gst_pd_pushsrc_base_init (gpointer g_class) { @@ -126,7 +126,7 @@ gst_pd_pushsrc_base_init (gpointer g_class) GST_LOG ("OUT"); } - +#endif static void gst_pd_pushsrc_class_init (GstPDPushSrcClass * klass) { @@ -188,7 +188,6 @@ static void gst_pd_pushsrc_init (GstPDPushSrc * src) { GST_LOG ("IN"); - GstBaseSrc *basesrc = GST_BASE_SRC (src); src->filename = NULL; src->fd = 0; @@ -335,7 +334,7 @@ gst_pd_pushsrc_create_read (GstBaseSrc * basesrc, guint64 offset, guint length, if (fstat (src->fd, &stat_results) < 0) goto could_not_stat; - GST_LOG_OBJECT (src, "offset + length = %"G_GUINT64_FORMAT " and filesize = %"G_GUINT64_FORMAT, offset + length, stat_results.st_size); + GST_LOG_OBJECT (src, "offset + length = %"G_GUINT64_FORMAT " and filesize = %"G_GUINT64_FORMAT, offset + length, (guint64)stat_results.st_size); while ((offset + length) > stat_results.st_size) { @@ -484,10 +483,8 @@ gst_pd_pushsrc_create (GstBaseSrc * basesrc, guint64 offset, guint length, GstBu { GST_LOG ("IN"); - GstPDPushSrc *pdsrc; GstFlowReturn ret; - pdsrc = GST_PD_PUSHSRC_CAST (basesrc); ret = gst_pd_pushsrc_create_read (basesrc, offset, length, buffer); GST_LOG ("OUT"); diff --git a/toggle/src/gsttoggle.c b/toggle/src/gsttoggle.c index 0363dda..5b7dd65 100755 --- a/toggle/src/gsttoggle.c +++ b/toggle/src/gsttoggle.c @@ -54,7 +54,7 @@ enum { PROP_0, PROP_BLOCK_DATA - + }; @@ -75,16 +75,16 @@ static GstFlowReturn gst_mytoggle_transform_ip (GstBaseTransform * trans, static gboolean gst_mytoggle_start (GstBaseTransform * trans); static gboolean gst_mytoggle_stop (GstBaseTransform * trans); +#if 0 static void gst_mytoggle_base_init (gpointer g_class) { } +#endif static void gst_mytoggle_finalize (GObject * object) { - GstMytoggle *mytoggle; - G_OBJECT_CLASS (gst_mytoggle_parent_class)->finalize (object); } @@ -105,9 +105,9 @@ gst_mytoggle_class_init (GstMytoggleClass * klass) g_object_class_install_property (gobject_class, PROP_BLOCK_DATA, g_param_spec_boolean ("block_data", "Data Block", - "Data Block", + "Data Block", DEFAULT_BLOCK_DATA, G_PARAM_READWRITE)); - + gobject_class->finalize = GST_DEBUG_FUNCPTR (gst_mytoggle_finalize); gst_element_class_set_details_simple (gstelement_class, @@ -138,8 +138,8 @@ static GstFlowReturn gst_mytoggle_transform_ip (GstBaseTransform * trans, GstBuffer * buf) { GstMytoggle *mytoggle = GST_MYTOGGLE (trans); - - if (mytoggle->block_data ==TRUE) + + if (mytoggle->block_data ==TRUE) return GST_BASE_TRANSFORM_FLOW_DROPPED; return GST_FLOW_OK; @@ -154,7 +154,7 @@ gst_mytoggle_set_property (GObject * object, guint prop_id, mytoggle = GST_MYTOGGLE (object); switch (prop_id) { - + case PROP_BLOCK_DATA: mytoggle->block_data = g_value_get_boolean (value); break; @@ -206,5 +206,5 @@ GST_PLUGIN_DEFINE (GST_VERSION_MAJOR, toggle, "Base transform plugin template", plugin_init, VERSION, "LGPL", "Samsung Electronics Co", "http://www.samsung.com/") - + -- 2.7.4 From ba23749e4087b024999da7df6e61df34bc0447ad Mon Sep 17 00:00:00 2001 From: Jeongmo Yang Date: Fri, 18 Mar 2016 15:03:42 +0900 Subject: [PATCH 13/16] [tizenipc] 1. Fix build warning, 2. Fix Svace issue Change-Id: Ibfb6e09221ab3e1b679e53b4093b85bbc3cc6f95 Signed-off-by: Jeongmo Yang --- packaging/gst-plugins-tizen.spec | 2 +- tizenipc/src/gsttizenipcsrc.c | 45 ++++++++++++++++++++-------------------- 2 files changed, 24 insertions(+), 23 deletions(-) diff --git a/packaging/gst-plugins-tizen.spec b/packaging/gst-plugins-tizen.spec index 9776b98..55efbf9 100644 --- a/packaging/gst-plugins-tizen.spec +++ b/packaging/gst-plugins-tizen.spec @@ -5,7 +5,7 @@ Name: gst-plugins-tizen Version: 1.0.0 Summary: GStreamer tizen plugins (common) -Release: 22 +Release: 23 Group: Multimedia/Framework Url: http://gstreamer.freedesktop.org/ License: LGPL-2.1+ diff --git a/tizenipc/src/gsttizenipcsrc.c b/tizenipc/src/gsttizenipcsrc.c index 6a2a7b3..f10b428 100644 --- a/tizenipc/src/gsttizenipcsrc.c +++ b/tizenipc/src/gsttizenipcsrc.c @@ -526,6 +526,11 @@ 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) { send_msg.id = TIZEN_IPC_BUFFER_RELEASE; @@ -538,6 +543,21 @@ static void gst_tizenipc_src_buffer_finalize(GstTizenipcSrcBuffer *ipc_buf) GST_ERROR_OBJECT(self, "invalid socket fd %d", self->socket_fd); } + /* send buffer signal */ + 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); + + self->live_buffer_count--; + g_cond_signal(&self->buffer_cond); + + g_mutex_unlock(&self->buffer_lock); + + gst_object_unref(self); + self = NULL; + +_BUFFER_FINALIZE_DONE: if (mm_buf) { for (i = 0 ; i < mm_buf->handle_num ; i++) { if (mm_buf->handle.bo[i]) { @@ -552,22 +572,6 @@ static void gst_tizenipc_src_buffer_finalize(GstTizenipcSrcBuffer *ipc_buf) mm_buf = NULL; } - /* send buffer signal */ - 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); - - self->live_buffer_count--; - g_cond_signal(&self->buffer_cond); - - g_mutex_unlock(&self->buffer_lock); - - if (self) { - gst_object_unref(self); - self = NULL; - } - free(ipc_buf); ipc_buf = NULL; @@ -607,10 +611,12 @@ static GstFlowReturn gst_tizenipc_src_create(GstPushSrc *psrc, GstBuffer **outbu again: if (gst_poll_wait (self->poll, GST_CLOCK_TIME_NONE) < 0) { + char str_error[64] = {'\0',}; if (errno == EBUSY) return GST_FLOW_FLUSHING; + strerror_r(errno, str_error, sizeof(str_error)); GST_ELEMENT_ERROR(self, RESOURCE, READ, ("Failed to read from sink"), - ("Poll failed on fd: %s", strerror (errno))); + ("Poll failed on fd: %s", str_error)); return GST_FLOW_ERROR; } @@ -861,11 +867,6 @@ _CREATE_FAILED: mm_buf = NULL; } - if (gst_memory) { - gst_memory_unref(gst_memory); - gst_memory = NULL; - } - if (gst_buf) { gst_buffer_unref(gst_buf); gst_buf = NULL; -- 2.7.4 From 3ef205953866730db028ca82182d527852c92392 Mon Sep 17 00:00:00 2001 From: Gilbok Lee Date: Fri, 18 Mar 2016 15:27:03 +0900 Subject: [PATCH 14/16] Fix Svace issue(WGID:42762) Change-Id: I69c5aa04a1ed39383f8501ae122a95279c12ae22 Signed-off-by: Gilbok Lee --- audioeq/src/gstaudioeq.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/audioeq/src/gstaudioeq.c b/audioeq/src/gstaudioeq.c index 3fe2751..5981851 100644 --- a/audioeq/src/gstaudioeq.c +++ b/audioeq/src/gstaudioeq.c @@ -868,7 +868,7 @@ gst_iir_equalizer_compute_frequencies (Gstaudioeq * audioeq, guint new_count) for (i = old_count; i < new_count; i++) { equ->bands[i] = g_object_new (GST_TYPE_IIR_EQUALIZER_BAND, NULL); /* otherwise they get names like 'iirequalizerband5' */ - sprintf (name, "band%u", i); + snprintf (name, sizeof(name), "band%u", i); gst_object_set_name (GST_OBJECT (equ->bands[i]), name); GST_DEBUG ("adding band[%d]=%p", i, equ->bands[i]); @@ -1046,9 +1046,9 @@ gst_audioeq_transform_ip (GstBaseTransform * base, GstBuffer * buf) if (G_UNLIKELY (audioeq->channels < 1 || equ->process == NULL)) { GST_DEBUG ("gst_audioeq_transform_ip return GST_FLOW_NOT_NEGOTIATED;"); if (G_UNLIKELY (equ->process == NULL)) - GST_DEBUG ("gst_audioeq_transform_ip equ->process "); + GST_DEBUG ("gst_audioeq_transform_ip equ->process "); if (G_UNLIKELY (audioeq->channels < 1)) - GST_DEBUG ("gst_audioeq_transform_ip audioeq->channels"); + GST_DEBUG ("gst_audioeq_transform_ip audioeq->channels"); return GST_FLOW_NOT_NEGOTIATED; } GST_DEBUG ("gst_audioeq_transform_ip BANDS_LOCK (equ);"); -- 2.7.4 From c305c8e3989543bb422207b7cd745de288f83432 Mon Sep 17 00:00:00 2001 From: NAMJEONGYOON Date: Thu, 17 Mar 2016 09:26:37 +0900 Subject: [PATCH 15/16] [evasimagesink] fix build warnings Change-Id: Ifbaad7f3f378a5f0bc0ce57bea7342bf7ea15d07 Signed-off-by: NAMJEONGYOON --- evasimagesink/src/gstevasimagesink.c | 59 ++++++++++++++++++------------------ 1 file changed, 30 insertions(+), 29 deletions(-) diff --git a/evasimagesink/src/gstevasimagesink.c b/evasimagesink/src/gstevasimagesink.c index 997915c..b782777 100755 --- a/evasimagesink/src/gstevasimagesink.c +++ b/evasimagesink/src/gstevasimagesink.c @@ -268,13 +268,6 @@ gst_evas_image_sink_finalize (GObject * object) G_OBJECT_CLASS (parent_class)->finalize (object); } - - -static void -gst_evas_image_sink_base_init (gpointer gclass) -{ -} - static void gst_evas_image_sink_class_init (GstEvasImageSinkClass *klass) { @@ -346,19 +339,21 @@ gst_evas_image_sink_fini (gpointer data, GObject *obj) if (esink->eo) { #ifdef USE_TBM_SURFACE EVASIMAGESINK_UNSET_EVAS_EVENT_CALLBACK (evas_object_evas_get(esink->eo)); - GST_DEBUG("unset EVASIMAGESINK_UNSET_EVAS_EVENT_CALLBACK esink : %p, esink->eo : %x", esink, esink->eo); + GST_DEBUG("unset EVASIMAGESINK_UNSET_EVAS_EVENT_CALLBACK esink : %p, esink->eo : %p", esink, esink->eo); #endif EVASIMAGESINK_UNSET_EVAS_OBJECT_EVENT_CALLBACK (esink->eo); - GST_DEBUG("unset EVASIMAGESINK_UNSET_EVAS_OBJECT_EVENT_CALLBACK esink : %p, esink->eo : %x", esink, esink->eo); + GST_DEBUG("unset EVASIMAGESINK_UNSET_EVAS_OBJECT_EVENT_CALLBACK esink : %p, esink->eo : %p", esink, esink->eo); evas_object_image_data_set(esink->eo, NULL); } #ifdef USE_TBM_SURFACE if (esink->display_buffer_lock) { - g_mutex_free (esink->display_buffer_lock); + g_mutex_clear (esink->display_buffer_lock); + g_slice_free (GMutex, esink->display_buffer_lock); esink->display_buffer_lock = NULL; } if (esink->flow_lock) { - g_mutex_free (esink->flow_lock); + g_mutex_clear (esink->flow_lock); + g_slice_free (GMutex, esink->flow_lock); esink->flow_lock = NULL; } esink->eo = NULL; @@ -368,7 +363,8 @@ gst_evas_image_sink_fini (gpointer data, GObject *obj) instance_lock_count--; g_mutex_unlock (instance_lock); if (instance_lock_count == 0) { - g_mutex_free (instance_lock); + g_mutex_clear (instance_lock); + g_slice_free (GMutex, instance_lock); instance_lock = NULL; } @@ -455,7 +451,7 @@ evas_image_sink_cb_pipe (void *data, int *buffer_index, unsigned int nbyte) GST_WARNING ("esink : %p, or eo is NULL returning", esink); return; } - GST_LOG("esink : %p, esink->eo : %x", esink, esink->eo); + GST_LOG("esink : %p, esink->eo : %p", esink, esink->eo); if (nbyte == SIZE_FOR_UPDATE_VISIBILITY) { if(!esink->object_show) { evas_object_hide(esink->eo); @@ -639,7 +635,7 @@ evas_image_sink_cb_pipe (void *data, int *buffer_index, unsigned int nbyte) GST_WARNING ("Cannot get image data from evas object or cannot get gstbuffer data"); evas_object_image_data_set(esink->eo, img_data); } else { - GST_DEBUG ("img_data(%x), buf_info.data:%x, esink->w(%d),esink->h(%d), esink->eo(%x)",img_data,buf_info.data,esink->w,esink->h,esink->eo); + GST_DEBUG ("img_data(%p), buf_info.data:%p, esink->w(%d),esink->h(%d), esink->eo(%p)",img_data,buf_info.data,esink->w,esink->h,esink->eo); memcpy (img_data, buf_info.data, esink->w * esink->h * COLOR_DEPTH); evas_object_image_pixels_dirty_set (esink->eo, 1); evas_object_image_data_set(esink->eo, img_data); @@ -648,7 +644,7 @@ evas_image_sink_cb_pipe (void *data, int *buffer_index, unsigned int nbyte) gst_buffer_unref (buf); } else { gst_buffer_map(buf, &buf_info, GST_MAP_READ); - GST_DEBUG ("buf_info.data(buf):%x, esink->eo(%x)",buf_info.data,esink->eo); + GST_DEBUG ("buf_info.data(buf):%p, esink->eo(%p)",buf_info.data,esink->eo); evas_object_image_data_set (esink->eo, buf_info.data); gst_buffer_unmap(buf, &buf_info); evas_object_image_pixels_dirty_set (esink->eo, 1); @@ -794,8 +790,10 @@ gst_evas_image_sink_init (GstEvasImageSink *esink) esink->present_data_addr = -1; #endif #ifdef USE_TBM_SURFACE - esink->display_buffer_lock = g_mutex_new (); - esink->flow_lock = g_mutex_new (); + esink->display_buffer_lock = g_slice_new (GMutex); + esink->flow_lock = g_slice_new (GMutex); + g_mutex_init (esink->display_buffer_lock); + g_mutex_init (esink->flow_lock); int i = 0; for (i=0; iis_buffer_allocated = FALSE; #endif if(!instance_lock) { - instance_lock = g_mutex_new(); + instance_lock = g_slice_new (GMutex); + g_mutex_init(instance_lock); } g_mutex_lock (instance_lock); instance_lock_count++; @@ -851,10 +850,10 @@ evas_callback_del_event (void *data, Evas *e, Evas_Object *obj, void *event_info if (esink->eo) { #ifdef USE_TBM_SURFACE EVASIMAGESINK_UNSET_EVAS_EVENT_CALLBACK (evas_object_evas_get(esink->eo)); - GST_DEBUG("unset EVASIMAGESINK_UNSET_EVAS_EVENT_CALLBACK esink : %p, esink->eo : %x", esink, esink->eo); + GST_DEBUG("unset EVASIMAGESINK_UNSET_EVAS_EVENT_CALLBACK esink : %p, esink->eo : %p", esink, esink->eo); #endif EVASIMAGESINK_UNSET_EVAS_OBJECT_EVENT_CALLBACK (esink->eo); - GST_DEBUG("unset EVASIMAGESINK_UNSET_EVAS_OBJECT_EVENT_CALLBACK esink : %p, esink->eo : %x", esink, esink->eo); + GST_DEBUG("unset EVASIMAGESINK_UNSET_EVAS_OBJECT_EVENT_CALLBACK esink : %p, esink->eo : %p", esink, esink->eo); evas_object_image_data_set(esink->eo, NULL); esink->eo = NULL; @@ -1123,8 +1122,6 @@ evas_image_sink_event_parse_data (GstEvasImageSink *esink, GstEvent *event) { const GstStructure *st; guint st_data_addr = 0; - gint st_data_width = 0; - gint st_data_height = 0; g_return_val_if_fail (event != NULL, FALSE); g_return_val_if_fail (esink != NULL, FALSE); @@ -1152,8 +1149,6 @@ gst_evas_image_sink_event (GstBaseSink *sink, GstEvent *event) { #ifdef USE_FIMCC GstEvasImageSink *esink = GST_EVASIMAGESINK (sink); - GstMessage *msg; - gchar *str; #endif switch (GST_EVENT_TYPE (event)) { case GST_EVENT_FLUSH_START: @@ -1189,7 +1184,9 @@ gst_evas_image_sink_change_state (GstElement *element, GstStateChange transition { GstStateChangeReturn ret_state = GST_STATE_CHANGE_SUCCESS; GstEvasImageSink *esink = NULL; +#ifdef USE_TBM_SURFACE GstFlowReturn ret=GST_FLOW_OK; +#endif esink = GST_EVASIMAGESINK(element); if(!esink) { @@ -1307,7 +1304,7 @@ gst_evas_image_sink_set_property (GObject *object, guint prop_id, const GValue * /* add evas object callbacks on a new evas image object */ EVASIMAGESINK_SET_EVAS_OBJECT_EVENT_CALLBACK (esink->eo, esink); #ifdef USE_TBM_SURFACE - GST_WARNING("register render callback [esink : %p, esink->eo : %x]", esink, esink->eo); + GST_WARNING("register render callback [esink : %p, esink->eo : %p]", esink, esink->eo); EVASIMAGESINK_SET_EVAS_EVENT_CALLBACK (evas_object_evas_get(esink->eo), esink); evas_object_geometry_get(esink->eo, &esink->eo_size.x, &esink->eo_size.y, &esink->eo_size.w, &esink->eo_size.h); GST_WARNING ("evas object size (x:%d, y:%d, w:%d, h:%d)", esink->eo_size.x, esink->eo_size.y, esink->eo_size.w, esink->eo_size.h); @@ -1319,7 +1316,7 @@ gst_evas_image_sink_set_property (GObject *object, guint prop_id, const GValue * GST_DEBUG("Enable gl zerocopy"); } #endif - GST_DEBUG("Evas Image Object(%x) is set", esink->eo); + GST_DEBUG("Evas Image Object(%p) is set", esink->eo); esink->is_evas_object_size_set = FALSE; esink->object_show = TRUE; esink->update_visibility = UPDATE_TRUE; @@ -1464,7 +1461,7 @@ gst_evas_image_sink_set_caps (GstBaseSink *base_sink, GstCaps *caps) int w, h; GstEvasImageSink *esink = GST_EVASIMAGESINK (base_sink); GstStructure *structure = NULL; - gchar *format = NULL; + const gchar *format = NULL; esink->is_evas_object_size_set = FALSE; r = evas_image_sink_get_size_from_caps (caps, &w, &h); @@ -1804,9 +1801,13 @@ gst_evas_image_sink_show_frame (GstVideoSink *video_sink, GstBuffer *buf) g_mutex_unlock(esink->display_buffer_lock); #endif - GST_DEBUG ("ecore_pipe_write() was called with gst_buf= %p.. gst_buf Vaddr=%p, mallocdata= %p", buf, buf_info.size, buf_info.memory); + GST_DEBUG ("ecore_pipe_write() was called with gst_buf= %p.. gst_buf size=%d, mallocdata= %p", buf, buf_info.size, buf_info.memory); } else { - GST_WARNING ("skip ecore_pipe_write(). becuase of esink->object_show(%d) index(%d)", esink->object_show, index); +#ifdef USE_TBM_SURFACE + GST_WARNING ("skip ecore_pipe_write(). becuase of esink->object_show(%d) index %d", esink->object_show, index); +#else + GST_WARNING ("skip ecore_pipe_write(). becuase of esink->object_show(%d)", esink->object_show); +#endif } gst_buffer_unmap(buf, &buf_info); g_mutex_unlock (instance_lock); -- 2.7.4 From 01716631cac33a05af1f86aab1e7314d03864b22 Mon Sep 17 00:00:00 2001 From: "Hyunsoo, Park" Date: Fri, 1 Apr 2016 11:45:28 +0900 Subject: [PATCH 16/16] Fix warning message by 'gst_element_post_message' because of parameter modification Change-Id: I13a5b6d27fa924619c5405d3110cd657903de431 Signed-off-by: Hyunsoo, Park --- wfdmanager/wfdbase/gstwfdbasesrc.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/wfdmanager/wfdbase/gstwfdbasesrc.c b/wfdmanager/wfdbase/gstwfdbasesrc.c index 6a87528..749a9a1 100755 --- a/wfdmanager/wfdbase/gstwfdbasesrc.c +++ b/wfdmanager/wfdbase/gstwfdbasesrc.c @@ -2071,7 +2071,7 @@ gst_wfd_base_src_loop (GstWFDBaseSrc * src) /* server closed the connection.*/ GST_ELEMENT_WARNING (src, RESOURCE, READ, (NULL), ("The server closed the connection.")); - gst_element_post_message (GST_ELEMENT_CAST (src), gst_message_new_element (GST_OBJECT_CAST (src), gst_structure_new ("GstWFDSrcSessionTimeout", NULL))); + gst_element_post_message (GST_ELEMENT_CAST (src), gst_message_new_element (GST_OBJECT_CAST (src), gst_structure_new ("GstWFDSrcSessionTimeout", NULL, NULL))); goto connect_error; default: -- 2.7.4