DIRECTFB_DIR=
endif
-#if USE_WAYLAND
-#WAYLAND_DIR=wayland
-#else
+if USE_WAYLAND
+WAYLAND_DIR=wayland
+else
WAYLAND_DIR=
-#endif
+endif
if USE_DAALA
DAALA_DIR=daala
wlbuffer.c \
wldisplay.c \
wlwindow.c \
+ scaler-protocol.c \
wlvideoformat.c \
- scaler-protocol.c
+ tizen-wlvideoformat.c
libgstwaylandsink_la_CFLAGS = $(GST_CFLAGS) $(GST_PLUGINS_BASE_CFLAGS) \
- $(WAYLAND_CFLAGS) $(GST_PLUGINS_BAD_CFLAGS)
+ $(WAYLAND_CFLAGS) $(GST_PLUGINS_BAD_CFLAGS) $(DRM_CFLAGS) $(TBM_CFLAGS) $(MMCOMMON_CFLAGS)
libgstwaylandsink_la_LIBADD = \
$(GST_PLUGINS_BASE_LIBS) \
-lgstvideo-$(GST_API_VERSION) \
- $(WAYLAND_LIBS) \
+ $(WAYLAND_LIBS) $(DRM_LIBS) $(TBM_LIBS)\
$(top_builddir)/gst-libs/gst/wayland/libgstwayland-$(GST_API_VERSION).la
libgstwaylandsink_la_LDFLAGS = $(GST_PLUGIN_LDFLAGS)
libgstwaylandsink_la_LIBTOOLFLAGS = $(GST_PLUGIN_LIBTOOLFLAGS)
wlbuffer.h \
wldisplay.h \
wlwindow.h \
+ scaler-client-protocol.h \
wlvideoformat.h \
- scaler-client-protocol.h
+ tizen-wlvideoformat.h
EXTRA_DIST = scaler.xml
CLEANFILES = scaler-protocol.c scaler-client-protocol.h
#endif
#include "gstwaylandsink.h"
+#ifdef GST_WLSINK_ENHANCEMENT
+#include <mm_types.h>
+#endif
#include "wlvideoformat.h"
#include "wlbuffer.h"
#include "wlshmallocator.h"
#include <gst/wayland/wayland.h>
#include <gst/video/videooverlay.h>
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+
+//#define DUMP_BUFFER
+
/* signals */
enum
{
enum
{
PROP_0,
- PROP_DISPLAY
+ PROP_DISPLAY,
+#ifdef GST_WLSINK_ENHANCEMENT
+ PROP_USE_TBM
+#endif
};
+int dump__cnt = 0;
GST_DEBUG_CATEGORY (gstwayland_debug);
#define GST_CAT_DEFAULT gstwayland_debug
GST_STATIC_CAPS (GST_VIDEO_CAPS_MAKE
("{ BGRx, BGRA, RGBx, xBGR, xRGB, RGBA, ABGR, ARGB, RGB, BGR, "
"RGB16, BGR16, YUY2, YVYU, UYVY, AYUV, NV12, NV21, NV16, "
+#ifdef GST_WLSINK_ENHANCEMENT
+ "SN12, ST12, "
+#endif
"YUV9, YVU9, Y41B, I420, YV12, Y42B, v308 }"))
);
static void
gst_wayland_sink_class_init (GstWaylandSinkClass * klass)
{
+ FUNCTION;
GObjectClass *gobject_class;
GstElementClass *gstelement_class;
GstBaseSinkClass *gstbasesink_class;
g_param_spec_string ("display", "Wayland Display name", "Wayland "
"display name to connect to, if not supplied via the GstContext",
NULL, G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
+
+ g_object_class_install_property (gobject_class, PROP_USE_TBM,
+ g_param_spec_boolean ("use-tbm",
+ "Use Tizen Buffer Memory insted of Shared memory",
+ "When enabled, Memory is alloced by TBM insted of SHM ", TRUE,
+ G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
}
+#ifdef DUMP_BUFFER
+int
+__write_rawdata (const char *file, const void *data, unsigned int size)
+{
+ FILE *fp;
+
+ fp = fopen (file, "wb");
+ if (fp == NULL)
+ return -1;
+
+ fwrite ((char *) data, sizeof (char), size, fp);
+ fclose (fp);
+
+ return 0;
+}
+#endif
static void
gst_wayland_sink_init (GstWaylandSink * sink)
{
+ FUNCTION;
+ sink->USE_TBM = TRUE;
g_mutex_init (&sink->display_lock);
g_mutex_init (&sink->render_lock);
}
gst_wayland_sink_get_property (GObject * object,
guint prop_id, GValue * value, GParamSpec * pspec)
{
+ FUNCTION;
GstWaylandSink *sink = GST_WAYLAND_SINK (object);
switch (prop_id) {
g_value_set_string (value, sink->display_name);
GST_OBJECT_UNLOCK (sink);
break;
+#ifdef GST_WLSINK_ENHANCEMENT
+ case PROP_USE_TBM:
+ g_value_set_boolean (value, sink->USE_TBM);
+ break;
+#endif
default:
G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
break;
gst_wayland_sink_set_property (GObject * object,
guint prop_id, const GValue * value, GParamSpec * pspec)
{
+ FUNCTION;
GstWaylandSink *sink = GST_WAYLAND_SINK (object);
switch (prop_id) {
sink->display_name = g_value_dup_string (value);
GST_OBJECT_UNLOCK (sink);
break;
+#ifdef GST_WLSINK_ENHANCEMENT
+ case PROP_USE_TBM:
+ sink->USE_TBM = g_value_get_boolean (value);
+ GST_LOG ("1:USE TBM 0: USE SHM set(%d)", sink->USE_TBM);
+ break;
+#endif
default:
G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
break;
static void
gst_wayland_sink_finalize (GObject * object)
{
+ FUNCTION;
GstWaylandSink *sink = GST_WAYLAND_SINK (object);
GST_DEBUG_OBJECT (sink, "Finalizing the sink..");
gst_wayland_sink_set_display_from_context (GstWaylandSink * sink,
GstContext * context)
{
+ FUNCTION;
struct wl_display *display;
GError *error = NULL;
("Failed to use the external wayland display: '%s'", error->message));
g_error_free (error);
}
+#ifdef GST_WLSINK_ENHANCEMENT
+ sink->display->USE_TBM = sink->USE_TBM;
+#endif
}
static gboolean
gst_wayland_sink_find_display (GstWaylandSink * sink)
{
+ FUNCTION;
GstQuery *query;
GstMessage *msg;
GstContext *context = NULL;
g_error_free (error);
ret = FALSE;
}
+#ifdef GST_WLSINK_ENHANCEMENT
+ sink->display->USE_TBM = sink->USE_TBM;
+#endif
}
}
}
static GstStateChangeReturn
gst_wayland_sink_change_state (GstElement * element, GstStateChange transition)
{
+ FUNCTION;
GstWaylandSink *sink = GST_WAYLAND_SINK (element);
GstStateChangeReturn ret = GST_STATE_CHANGE_SUCCESS;
static void
gst_wayland_sink_set_context (GstElement * element, GstContext * context)
{
+ FUNCTION;
GstWaylandSink *sink = GST_WAYLAND_SINK (element);
if (gst_context_has_context_type (context,
g_mutex_lock (&sink->display_lock);
if (G_LIKELY (!sink->display))
gst_wayland_sink_set_display_from_context (sink, context);
- else
+ else {
GST_WARNING_OBJECT (element, "changing display handle is not supported");
+#ifdef GST_WLSINK_ENHANCEMENT
+ g_mutex_unlock (&sink->display_lock);
+ return;
+#endif
+ }
g_mutex_unlock (&sink->display_lock);
}
static GstCaps *
gst_wayland_sink_get_caps (GstBaseSink * bsink, GstCaps * filter)
{
+ FUNCTION;
GstWaylandSink *sink;
GstCaps *caps;
GValue value = G_VALUE_INIT;
GArray *formats;
gint i;
+#ifdef GST_WLSINK_ENHANCEMENT
+ uint32_t tbm_fmt;
+#endif
enum wl_shm_format fmt;
g_value_init (&list, GST_TYPE_LIST);
g_value_init (&value, G_TYPE_STRING);
+#ifdef GST_WLSINK_ENHANCEMENT
+ if (sink->display->USE_TBM)
+ formats = sink->display->tbm_formats;
+ else /* SHM */
+#endif
+ formats = sink->display->formats;
- formats = sink->display->formats;
for (i = 0; i < formats->len; i++) {
+#ifdef GST_WLSINK_ENHANCEMENT
+ if (sink->USE_TBM) {
+ tbm_fmt = g_array_index (formats, uint32_t, i);
+ g_value_set_string (&value, gst_wl_tbm_format_to_string (tbm_fmt));
+ gst_value_list_append_value (&list, &value);
+ /* TBM doesn't support SN12. So we add SN12 manually as supported format.
+ * SN12 is exactly same with NV12.
+ */
+ if (tbm_fmt == TBM_FORMAT_NV12) {
+ g_value_set_string (&value,
+ gst_video_format_to_string (GST_VIDEO_FORMAT_SN12));
+ gst_value_list_append_value (&list, &value);
+ }
+ } else { /* USE SHM */
+ fmt = g_array_index (formats, uint32_t, i);
+ g_value_set_string (&value, gst_wl_shm_format_to_string (fmt));
+ gst_value_list_append_value (&list, &value);
+ }
+#else /* open source */
fmt = g_array_index (formats, uint32_t, i);
g_value_set_string (&value, gst_wl_shm_format_to_string (fmt));
gst_value_list_append_value (&list, &value);
+#endif
}
caps = gst_caps_make_writable (caps);
static gboolean
gst_wayland_sink_set_caps (GstBaseSink * bsink, GstCaps * caps)
{
+ FUNCTION;
GstWaylandSink *sink;
GstBufferPool *newpool;
GstVideoInfo info;
+#ifdef GST_WLSINK_ENHANCEMENT
+ uint32_t tbm_format;
+#endif
enum wl_shm_format format;
+
GArray *formats;
gint i;
GstStructure *structure;
/* extract info from caps */
if (!gst_video_info_from_caps (&info, caps))
goto invalid_format;
-
+#ifdef GST_WLSINK_ENHANCEMENT
+ sink->caps = gst_caps_copy (caps);
+ if (sink->USE_TBM) {
+ tbm_format =
+ gst_video_format_to_wl_tbm_format (GST_VIDEO_INFO_FORMAT (&info));
+ if ((gint) tbm_format == -1)
+ goto invalid_format;
+ } else {
+ format = gst_video_format_to_wl_shm_format (GST_VIDEO_INFO_FORMAT (&info));
+ if ((gint) format == -1)
+ goto invalid_format;
+ }
+#else /* open source */
format = gst_video_format_to_wl_shm_format (GST_VIDEO_INFO_FORMAT (&info));
+
if ((gint) format == -1)
goto invalid_format;
+#endif
/* verify we support the requested format */
+#ifdef GST_WLSINK_ENHANCEMENT
+ if (sink->display->USE_TBM) {
+ GST_ERROR ("USE TBM FORMAT");
+ formats = sink->display->tbm_formats;
+ for (i = 0; i < formats->len; i++) {
+ if (g_array_index (formats, uint32_t, i) == tbm_format)
+ break;
+ }
+ } else { /* USE SHM */
+ GST_ERROR ("USE SHM FORMAT");
+ formats = sink->display->formats;
+ for (i = 0; i < formats->len; i++) {
+ if (g_array_index (formats, uint32_t, i) == format)
+ break;
+ }
+ }
+#else /* open source */
+
formats = sink->display->formats;
for (i = 0; i < formats->len; i++) {
if (g_array_index (formats, uint32_t, i) == format)
break;
}
-
+#endif
if (i >= formats->len)
goto unsupported_format;
+#ifdef GST_WLSINK_ENHANCEMENT
+ if (sink->USE_TBM) {
+ if (GST_VIDEO_INFO_FORMAT (&info) == GST_VIDEO_FORMAT_SN12 ||
+ GST_VIDEO_INFO_FORMAT (&info) == GST_VIDEO_FORMAT_ST12) {
+ sink->display->is_native_format = TRUE;
+
+ /* store the video info */
+ sink->video_info = info;
+ sink->video_info_changed = TRUE;
+ } else {
+ sink->display->is_native_format = FALSE;
+ GstWlShmAllocator *self =
+ GST_WL_SHM_ALLOCATOR (gst_wl_shm_allocator_get ());
+ self->display = sink->display;
+ /* create a new pool for the new configuration */
+ newpool = gst_video_buffer_pool_new ();
+ if (!newpool)
+ goto pool_failed;
+
+ structure = gst_buffer_pool_get_config (newpool);
+ gst_buffer_pool_config_set_params (structure, caps, info.size, 6, 0);
+ gst_buffer_pool_config_set_allocator (structure,
+ gst_wl_shm_allocator_get (), NULL);
+ if (!gst_buffer_pool_set_config (newpool, structure))
+ goto config_failed;
+
+ /* store the video info */
+ sink->video_info = info;
+ sink->video_info_changed = TRUE;
+
+ gst_object_replace ((GstObject **) & sink->pool, (GstObject *) newpool);
+ gst_object_unref (newpool);
+ }
+ } else { /* USE SHM */
+
+ GstWlShmAllocator *self =
+ GST_WL_SHM_ALLOCATOR (gst_wl_shm_allocator_get ());
+ self->display = sink->display;
+
+ /* create a new pool for the new configuration */
+ newpool = gst_video_buffer_pool_new ();
+ if (!newpool)
+ goto pool_failed;
+
+ structure = gst_buffer_pool_get_config (newpool);
+ gst_buffer_pool_config_set_params (structure, caps, info.size, 6, 0);
+ gst_buffer_pool_config_set_allocator (structure,
+ gst_wl_shm_allocator_get (), NULL);
+ if (!gst_buffer_pool_set_config (newpool, structure))
+ goto config_failed;
+
+ /* store the video info */
+ sink->video_info = info;
+ sink->video_info_changed = TRUE;
+
+ gst_object_replace ((GstObject **) & sink->pool, (GstObject *) newpool);
+ gst_object_unref (newpool);
+ }
+#else /*open source */
/* create a new pool for the new configuration */
newpool = gst_video_buffer_pool_new ();
if (!newpool)
goto pool_failed;
structure = gst_buffer_pool_get_config (newpool);
- gst_buffer_pool_config_set_params (structure, caps, info.size, 2, 0);
- gst_buffer_pool_config_set_allocator (structure, gst_wl_shm_allocator_get (),
- NULL);
+ gst_buffer_pool_config_set_params (structure, caps, info.size, 6, 0);
+ gst_buffer_pool_config_set_allocator (structure,
+ gst_wl_shm_allocator_get (), NULL);
if (!gst_buffer_pool_set_config (newpool, structure))
goto config_failed;
gst_object_replace ((GstObject **) & sink->pool, (GstObject *) newpool);
gst_object_unref (newpool);
+#endif
return TRUE;
}
unsupported_format:
{
+#ifdef GST_WLSINK_ENHANCEMENT
+ if (sink->USE_TBM)
+ GST_DEBUG_OBJECT (sink, "Format %s is not available on the display",
+ gst_wl_tbm_format_to_string (tbm_format));
+ else /*USE SHM */
+ GST_DEBUG_OBJECT (sink, "Format %s is not available on the display",
+ gst_wl_shm_format_to_string (format));
+#else /*open source */
GST_DEBUG_OBJECT (sink, "Format %s is not available on the display",
gst_wl_shm_format_to_string (format));
+#endif
return FALSE;
}
pool_failed:
static gboolean
gst_wayland_sink_propose_allocation (GstBaseSink * bsink, GstQuery * query)
{
+ FUNCTION;
GstWaylandSink *sink = GST_WAYLAND_SINK (bsink);
GstStructure *config;
guint size, min_bufs, max_bufs;
+#ifdef GST_WLSINK_ENHANCEMENT
+ gboolean need_pool;
+ GstCaps *caps;
+ if (sink->USE_TBM) {
+ if (sink->display->is_native_format == TRUE)
+ return TRUE;
+ gst_query_parse_allocation (query, &caps, &need_pool);
+
+ if (caps == NULL) {
+ GST_DEBUG_OBJECT (bsink, "no caps specified");
+ return FALSE;
+ }
+ }
+#endif
config = gst_buffer_pool_get_config (sink->pool);
gst_buffer_pool_config_get_params (config, NULL, &size, &min_bufs, &max_bufs);
static GstFlowReturn
gst_wayland_sink_preroll (GstBaseSink * bsink, GstBuffer * buffer)
{
+ FUNCTION;
GST_DEBUG_OBJECT (bsink, "preroll buffer %p", buffer);
return gst_wayland_sink_render (bsink, buffer);
}
static void
frame_redraw_callback (void *data, struct wl_callback *callback, uint32_t time)
{
+ FUNCTION;
GstWaylandSink *sink = data;
GST_LOG ("frame_redraw_cb");
static void
render_last_buffer (GstWaylandSink * sink)
{
+ FUNCTION;
GstWlBuffer *wlbuffer;
const GstVideoInfo *info = NULL;
struct wl_surface *surface;
g_atomic_int_set (&sink->redraw_pending, TRUE);
callback = wl_surface_frame (surface);
+ /* frame_callback_listener is called when wayland-client finish rendering the wl_buffer */
wl_callback_add_listener (callback, &frame_callback_listener, sink);
if (G_UNLIKELY (sink->video_info_changed)) {
static GstFlowReturn
gst_wayland_sink_render (GstBaseSink * bsink, GstBuffer * buffer)
{
+ FUNCTION;
GstWaylandSink *sink = GST_WAYLAND_SINK (bsink);
GstBuffer *to_render;
GstWlBuffer *wlbuffer;
g_mutex_lock (&sink->render_lock);
- GST_LOG_OBJECT (sink, "render buffer %p", buffer);
+ GST_ERROR_OBJECT (sink, "render buffer %p", buffer);
if (G_UNLIKELY (!sink->window)) {
/* ask for window handle. Unlock render_lock while doing that because
gst_wl_window_new_toplevel (sink->display, &sink->video_info);
}
}
-
/* drop buffers until we get a frame callback */
if (g_atomic_int_get (&sink->redraw_pending) == TRUE)
goto done;
-
/* make sure that the application has called set_render_rectangle() */
if (G_UNLIKELY (sink->window->render_rectangle.w == 0))
goto no_window_size;
- wlbuffer = gst_buffer_get_wl_buffer (buffer);
+#ifdef GST_WLSINK_ENHANCEMENT
+ sink->display->tbm_need_limit_idx = FALSE;
+ wlbuffer = gst_buffer_get_wl_buffer (buffer);
if (G_LIKELY (wlbuffer && wlbuffer->display == sink->display)) {
- GST_LOG_OBJECT (sink, "buffer %p has a wl_buffer from our display, "
- "writing directly", buffer);
+ GST_LOG_OBJECT (sink, "buffer %p has a wl_buffer from our display, " "writing directly", buffer); // s/w codec case
+ GST_INFO ("wl_buffer (%p)", wlbuffer->wlbuffer);
to_render = buffer;
+
+#ifdef DUMP_BUFFER
+ GstMemory *mem;
+ GstMapInfo mem_info = GST_MAP_INFO_INIT;
+ int size = GST_VIDEO_INFO_SIZE (&sink->video_info);
+ mem = gst_buffer_peek_memory (to_render, 0);
+ gst_memory_map (mem, &mem_info, GST_MAP_READ);
+ void *data;
+ data = mem_info.data;
+ int ret;
+ char file_name[128];
+
+ sprintf (file_name, "/home/owner/DUMP/_WLSINK_OUT_DUMP_%2.2d.dump",
+ dump__cnt++);
+ ret = __write_rawdata (file_name, data, size);
+ if (ret) {
+ GST_ERROR ("_write_rawdata() failed");
+ }
+ GST_ERROR ("DUMP IMAGE %d, size (%d)", dump__cnt, size);
+ gst_memory_unmap (mem, &mem_info);
+#endif
} else {
GstMemory *mem;
struct wl_buffer *wbuf = NULL;
- GST_LOG_OBJECT (sink, "buffer %p does not have a wl_buffer from our "
- "display, creating it", buffer);
-
+ GST_LOG_OBJECT (sink, "buffer %p does not have a wl_buffer from our " "display, creating it", buffer); //videotestsrc case , s/w codec too
mem = gst_buffer_peek_memory (buffer, 0);
-
if (gst_is_wl_shm_memory (mem)) {
+ FUNCTION;
wbuf = gst_wl_shm_memory_construct_wl_buffer (mem, sink->display,
&sink->video_info);
}
+ if (wbuf) {
+ gst_buffer_add_wl_buffer (buffer, wbuf, sink->display); //careat GstWlBuffer and add gstbuffer, wlbuffer, display and etc
+ to_render = buffer;
+
+ } else {
+ GstMapInfo src;
+ /* we don't know how to create a wl_buffer directly from the provided
+ * memory, so we have to copy the data to a memory that we know how
+ * to handle... */
+
+ GST_LOG_OBJECT (sink, "buffer %p is not from our pool", buffer);
+ GST_LOG_OBJECT (sink, "buffer %p cannot have a wl_buffer, " "copying", buffer); //omx codec case
+
+ if (sink->USE_TBM && sink->display->is_native_format) {
+ /* in case of SN12 or ST12 */
+ GstMemory *mem;
+ struct wl_buffer *wbuf = NULL;
+ GstMapInfo mem_info = GST_MAP_INFO_INIT;
+ MMVideoBuffer *mm_video_buf = NULL;
+
+ mem = gst_buffer_peek_memory (buffer, 1);
+ gst_memory_map (mem, &mem_info, GST_MAP_READ);
+ mm_video_buf = (MMVideoBuffer *) mem_info.data;
+ gst_memory_unmap (mem, &mem_info);
+
+ if (mm_video_buf == NULL) {
+ GST_WARNING_OBJECT (sink, "mm_video_buf is NULL. Skip rendering");
+ return ret;
+ }
+ /* assign mm_video_buf info */
+ if (mm_video_buf->type == MM_VIDEO_BUFFER_TYPE_TBM_BO) {
+ GST_DEBUG_OBJECT (sink, "TBM bo %p %p %p", mm_video_buf->handle.bo[0],
+ mm_video_buf->handle.bo[1], mm_video_buf->handle.bo[2]);
+ sink->display->native_video_size = 0;
+ for (int i = 0; i < NV_BUF_PLANE_NUM; i++) {
+ if (mm_video_buf->handle.bo[i] != NULL) {
+ sink->display->bo[i] = mm_video_buf->handle.bo[i];
+ } else {
+ sink->display->bo[i] = 0;
+ }
+ sink->display->plane_size[i] = mm_video_buf->size[i];
+ sink->display->stride_width[i] = mm_video_buf->stride_width[i];
+ sink->display->stride_height[i] = mm_video_buf->stride_height[i];
+ sink->display->native_video_size += sink->display->plane_size[i];
+ }
+ } else {
+ GST_ERROR_OBJECT (sink, "Buffer type is not TBM");
+ return ret;
+ }
+ wlbuffer = gst_buffer_get_wl_buffer (buffer);
+ if (G_UNLIKELY (!wlbuffer)) {
+ wbuf =
+ gst_wl_shm_memory_construct_wl_buffer (mem, sink->display,
+ &sink->video_info);
+ if (G_UNLIKELY (!wbuf))
+ goto no_wl_buffer;
+
+ gst_buffer_add_wl_buffer (buffer, wbuf, sink->display);
+ }
+ } else if (sink->USE_TBM && !sink->display->is_native_format) {
+
+ sink->display->tbm_need_limit_idx = TRUE;
+
+ /* sink->pool always exists (created in set_caps), but it may not
+ * be active if upstream is not using it */
+ if (!gst_buffer_pool_is_active (sink->pool)
+ && !gst_buffer_pool_set_active (sink->pool, TRUE))
+ goto activate_failed;
+
+ ret = gst_buffer_pool_acquire_buffer (sink->pool, &to_render, NULL);
+ if (ret != GST_FLOW_OK)
+ goto no_buffer;
+
+ //GstMemory *mem;
+ //mem = gst_buffer_peek_memory (to_render, 0);
+ //if (gst_is_wl_shm_memory (mem)) {
+ GST_INFO ("to_render buffer is our buffer");
+ //}
+ /* the first time we acquire a buffer,
+ * we need to attach a wl_buffer on it */
+ wlbuffer = gst_buffer_get_wl_buffer (buffer);
+ if (G_UNLIKELY (!wlbuffer)) {
+ mem = gst_buffer_peek_memory (to_render, 0);
+ wbuf = gst_wl_shm_memory_construct_wl_buffer (mem, sink->display,
+ &sink->video_info);
+ if (G_UNLIKELY (!wbuf))
+ goto no_wl_buffer;
+
+ wlbuffer = gst_buffer_add_wl_buffer (to_render, wbuf, sink->display);
+ }
+
+ gst_buffer_map (buffer, &src, GST_MAP_READ);
+ gst_buffer_fill (to_render, 0, src.data, src.size);
+ gst_buffer_unmap (buffer, &src);
+ } else { /* USE SHM */
+ /* sink->pool always exists (created in set_caps), but it may not
+ * be active if upstream is not using it */
+ if (!gst_buffer_pool_is_active (sink->pool) &&
+ !gst_buffer_pool_set_active (sink->pool, TRUE))
+ goto activate_failed;
+ ret = gst_buffer_pool_acquire_buffer (sink->pool, &to_render, NULL);
+ if (ret != GST_FLOW_OK)
+ goto no_buffer;
+ /* the first time we acquire a buffer,
+ * we need to attach a wl_buffer on it */
+ wlbuffer = gst_buffer_get_wl_buffer (buffer);
+ if (G_UNLIKELY (!wlbuffer)) {
+ mem = gst_buffer_peek_memory (to_render, 0);
+ wbuf = gst_wl_shm_memory_construct_wl_buffer (mem, sink->display,
+ &sink->video_info);
+ if (G_UNLIKELY (!wbuf))
+ goto no_wl_buffer;
+
+ gst_buffer_add_wl_buffer (to_render, wbuf, sink->display);
+ }
+
+ gst_buffer_map (buffer, &src, GST_MAP_READ);
+ gst_buffer_fill (to_render, 0, src.data, src.size);
+ gst_buffer_unmap (buffer, &src);
+ }
+ }
+ }
+
+ if (sink->USE_TBM && sink->display->is_native_format) {
+ if (G_UNLIKELY (buffer == sink->last_buffer)) {
+ GST_LOG_OBJECT (sink, "Buffer already being rendered");
+ goto done;
+ }
+ gst_buffer_replace (&sink->last_buffer, buffer);
+ render_last_buffer (sink);
+
+ goto done;
+ } else { /* USE SHM or normal format */
+ /* drop double rendering */
+ if (G_UNLIKELY (buffer == sink->last_buffer)) {
+ GST_LOG_OBJECT (sink, "Buffer already being rendered");
+ goto done;
+ }
+ gst_buffer_replace (&sink->last_buffer, to_render);
+ render_last_buffer (sink);
+
+ if (buffer != to_render)
+ gst_buffer_unref (to_render);
+
+ goto done;
+ }
+
+#else /* open source */
+
+ wlbuffer = gst_buffer_get_wl_buffer (buffer);
+
+ if (G_LIKELY (wlbuffer && wlbuffer->display == sink->display)) {
+ GST_LOG_OBJECT (sink,
+ "buffer %p has a wl_buffer from our display, " "writing directly",
+ buffer);
+ GST_INFO ("wl_buffer (%p)", wlbuffer->wlbuffer);
+ to_render = buffer;
+
+ } else {
+ GstMemory *mem;
+ struct wl_buffer *wbuf = NULL;
+ GST_LOG_OBJECT (sink,
+ "buffer %p does not have a wl_buffer from our " "display, creating it",
+ buffer);
+ mem = gst_buffer_peek_memory (buffer, 0);
+ if (gst_is_wl_shm_memory (mem)) {
+ FUNCTION;
+ wbuf = gst_wl_shm_memory_construct_wl_buffer (mem, sink->display,
+ &sink->video_info);
+ }
if (wbuf) {
gst_buffer_add_wl_buffer (buffer, wbuf, sink->display);
to_render = buffer;
+
} else {
GstMapInfo src;
/* we don't know how to create a wl_buffer directly from the provided
* memory, so we have to copy the data to a memory that we know how
* to handle... */
- GST_LOG_OBJECT (sink, "buffer %p cannot have a wl_buffer, "
- "copying to wl_shm memory", buffer);
-
+ GST_LOG_OBJECT (sink, "buffer %p is not from our pool", buffer);
+ GST_LOG_OBJECT (sink, "buffer %p cannot have a wl_buffer, " "copying", buffer); //omx codec case
/* sink->pool always exists (created in set_caps), but it may not
* be active if upstream is not using it */
if (!gst_buffer_pool_is_active (sink->pool) &&
if (G_UNLIKELY (!wbuf))
goto no_wl_buffer;
- gst_buffer_add_wl_buffer (buffer, wbuf, sink->display);
+ gst_buffer_add_wl_buffer (to_render, wbuf, sink->display);
}
gst_buffer_map (buffer, &src, GST_MAP_READ);
gst_buffer_unmap (buffer, &src);
}
}
-
/* drop double rendering */
- if (G_UNLIKELY (to_render == sink->last_buffer)) {
+ if (G_UNLIKELY (buffer == sink->last_buffer)) {
GST_LOG_OBJECT (sink, "Buffer already being rendered");
goto done;
}
if (buffer != to_render)
gst_buffer_unref (to_render);
+
goto done;
+#endif /* GST_WLSINK_ENHANCEMENT */
+
no_window_size:
{
GST_ELEMENT_ERROR (sink, RESOURCE, WRITE,
static void
gst_wayland_sink_set_window_handle (GstVideoOverlay * overlay, guintptr handle)
{
+ FUNCTION;
GstWaylandSink *sink = GST_WAYLAND_SINK (overlay);
struct wl_surface *surface = (struct wl_surface *) handle;
g_return_if_fail (sink != NULL);
-
+#ifdef GST_WLSINK_ENHANCEMENT
+ if (sink->window != NULL) {
+ GST_WARNING_OBJECT (sink, "changing window handle is not supported");
+ return;
+ }
+#endif
g_mutex_lock (&sink->render_lock);
GST_DEBUG_OBJECT (sink, "Setting window handle %" GST_PTR_FORMAT,
gst_wayland_sink_set_render_rectangle (GstVideoOverlay * overlay,
gint x, gint y, gint w, gint h)
{
+ FUNCTION;
GstWaylandSink *sink = GST_WAYLAND_SINK (overlay);
g_return_if_fail (sink != NULL);
static void
gst_wayland_sink_expose (GstVideoOverlay * overlay)
{
+ FUNCTION;
GstWaylandSink *sink = GST_WAYLAND_SINK (overlay);
g_return_if_fail (sink != NULL);
static void
gst_wayland_sink_begin_geometry_change (GstWaylandVideo * video)
{
+ FUNCTION;
GstWaylandSink *sink = GST_WAYLAND_SINK (video);
g_return_if_fail (sink != NULL);
static void
gst_wayland_sink_end_geometry_change (GstWaylandVideo * video)
{
+ FUNCTION;
GstWaylandSink *sink = GST_WAYLAND_SINK (video);
g_return_if_fail (sink != NULL);
#include "wlwindow.h"
G_BEGIN_DECLS
-
#define GST_TYPE_WAYLAND_SINK \
(gst_wayland_sink_get_type())
#define GST_WAYLAND_SINK(obj) \
(G_TYPE_CHECK_CLASS_TYPE((klass),GST_TYPE_WAYLAND_SINK))
#define GST_WAYLAND_SINK_GET_CLASS(inst) \
(G_TYPE_INSTANCE_GET_CLASS ((inst), GST_TYPE_WAYLAND_SINK, GstWaylandSinkClass))
-
typedef struct _GstWaylandSink GstWaylandSink;
typedef struct _GstWaylandSinkClass GstWaylandSinkClass;
gboolean redraw_pending;
GMutex render_lock;
GstBuffer *last_buffer;
+#ifdef GST_WLSINK_ENHANCEMENT
+ gboolean USE_TBM;
+ GstCaps *caps;
+#endif
};
struct _GstWaylandSinkClass
GstVideoSinkClass parent;
};
-GType gst_wayland_sink_get_type (void) G_GNUC_CONST;
+GType
+gst_wayland_sink_get_type (void)
+ G_GNUC_CONST;
G_END_DECLS
-
#endif /* __GST_WAYLAND_VIDEO_SINK_H__ */
--- /dev/null
+/* GStreamer Wayland video sink
+ *
+ * Copyright (C) 2011 Intel Corporation
+ * Copyright (C) 2011 Sreerenj Balachandran <sreerenj.balachandran@intel.com>
+ * Copyright (C) 2012 Wim Taymans <wim.taymans@gmail.com>
+ * Copyright (C) 2014 Collabora Ltd.
+ *
+ * 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 <config.h>
+#endif
+#include "tizen-wlvideoformat.h"
+#ifdef GST_WLSINK_ENHANCEMENT
+
+GST_DEBUG_CATEGORY_EXTERN (gstwayland_debug);
+#define GST_CAT_DEFAULT gstwayland_debug
+
+typedef struct
+{
+ uint32_t wl_format;
+ GstVideoFormat gst_format;
+} wl_TbmVideoFormat;
+
+static const wl_TbmVideoFormat tbm_formats[] = {
+#if G_BYTE_ORDER == G_BIG_ENDIAN
+ {TBM_FORMAT_XRGB8888, GST_VIDEO_FORMAT_xRGB},
+ {TBM_FORMAT_XBGR8888, GST_VIDEO_FORMAT_xBGR},
+ {TBM_FORMAT_RGBX8888, GST_VIDEO_FORMAT_RGBx},
+ {TBM_FORMAT_BGRX8888, GST_VIDEO_FORMAT_BGRx},
+ {TBM_FORMAT_ARGB8888, GST_VIDEO_FORMAT_ARGB},
+ {TBM_FORMAT_ABGR8888, GST_VIDEO_FORMAT_RGBA},
+ {TBM_FORMAT_RGBA8888, GST_VIDEO_FORMAT_RGBA},
+ {TBM_FORMAT_BGRA8888, GST_VIDEO_FORMAT_BGRA},
+#else
+ {TBM_FORMAT_XRGB8888, GST_VIDEO_FORMAT_BGRx},
+ {TBM_FORMAT_XBGR8888, GST_VIDEO_FORMAT_RGBx},
+ {TBM_FORMAT_RGBX8888, GST_VIDEO_FORMAT_xBGR},
+ {TBM_FORMAT_BGRX8888, GST_VIDEO_FORMAT_xRGB},
+ {TBM_FORMAT_ARGB8888, GST_VIDEO_FORMAT_BGRA},
+ {TBM_FORMAT_ABGR8888, GST_VIDEO_FORMAT_RGBA},
+ {TBM_FORMAT_RGBA8888, GST_VIDEO_FORMAT_ABGR},
+ {TBM_FORMAT_BGRA8888, GST_VIDEO_FORMAT_ARGB},
+#endif
+ {TBM_FORMAT_RGB565, GST_VIDEO_FORMAT_RGB16},
+ {TBM_FORMAT_BGR565, GST_VIDEO_FORMAT_BGR16},
+ {TBM_FORMAT_RGB888, GST_VIDEO_FORMAT_RGB},
+ {TBM_FORMAT_BGR888, GST_VIDEO_FORMAT_BGR},
+ {TBM_FORMAT_YUYV, GST_VIDEO_FORMAT_YUY2},
+ {TBM_FORMAT_YVYU, GST_VIDEO_FORMAT_YVYU},
+ {TBM_FORMAT_UYVY, GST_VIDEO_FORMAT_UYVY},
+ {TBM_FORMAT_AYUV, GST_VIDEO_FORMAT_AYUV},
+ {TBM_FORMAT_NV12, GST_VIDEO_FORMAT_NV12},
+ {TBM_FORMAT_NV21, GST_VIDEO_FORMAT_NV21},
+ {TBM_FORMAT_NV16, GST_VIDEO_FORMAT_NV16},
+ {TBM_FORMAT_YUV410, GST_VIDEO_FORMAT_YUV9},
+ {TBM_FORMAT_YVU410, GST_VIDEO_FORMAT_YVU9},
+ {TBM_FORMAT_YUV411, GST_VIDEO_FORMAT_Y41B},
+ {TBM_FORMAT_YUV420, GST_VIDEO_FORMAT_I420},
+ {TBM_FORMAT_YVU420, GST_VIDEO_FORMAT_YV12},
+ {TBM_FORMAT_YUV422, GST_VIDEO_FORMAT_Y42B},
+ {TBM_FORMAT_YUV444, GST_VIDEO_FORMAT_v308},
+ {TBM_FORMAT_NV12MT, GST_VIDEO_FORMAT_ST12},
+ {TBM_FORMAT_NV12, GST_VIDEO_FORMAT_SN12},
+};
+
+uint32_t
+gst_video_format_to_wl_tbm_format (GstVideoFormat format)
+{
+ guint i;
+ for (i = 0; i < G_N_ELEMENTS (tbm_formats); i++)
+ if (tbm_formats[i].gst_format == format)
+ return tbm_formats[i].wl_format;
+ GST_WARNING ("wayland tbm video format not found");
+ return -1;
+}
+
+GstVideoFormat
+gst_wl_tbm_format_to_video_format (uint32_t wl_format)
+{
+ guint i;
+
+ for (i = 0; i < G_N_ELEMENTS (tbm_formats); i++)
+ if (tbm_formats[i].wl_format == wl_format)
+ return tbm_formats[i].gst_format;
+
+ GST_WARNING ("gst video format not found");
+ return GST_VIDEO_FORMAT_UNKNOWN;
+}
+
+const gchar *
+gst_wl_tbm_format_to_string (uint32_t wl_format)
+{
+ return gst_video_format_to_string
+ (gst_wl_tbm_format_to_video_format (wl_format));
+}
+#endif
--- /dev/null
+/* GStreamer Wayland video sink
+ *
+ * Copyright (C) 2011 Intel Corporation
+ * Copyright (C) 2011 Sreerenj Balachandran <sreerenj.balachandran@intel.com>
+ * Copyright (C) 2012 Wim Taymans <wim.taymans@gmail.com>
+ * Copyright (C) 2014 Collabora Ltd.
+ *
+ * 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_WL_VIDEO_FORMAT_H__
+#define __GST_TIZEN_WL_VIDEO_FORMAT_H__
+
+#include <wayland-client.h>
+#include <gst/video/video.h>
+
+#ifdef GST_WLSINK_ENHANCEMENT
+#include <tbm_surface.h>
+
+G_BEGIN_DECLS
+ uint32_t gst_video_format_to_wl_tbm_format (GstVideoFormat format);
+GstVideoFormat gst_wl_tbm_format_to_video_format (uint32_t wl_format);
+
+const gchar *gst_wl_tbm_format_to_string (uint32_t wl_format);
+
+G_END_DECLS
+#endif
+#endif
static void
gst_wl_buffer_dispose (GObject * gobject)
{
+ FUNCTION;
GstWlBuffer *self = GST_WL_BUFFER (gobject);
GST_TRACE_OBJECT (self, "dispose");
static void
gst_wl_buffer_finalize (GObject * gobject)
{
+ FUNCTION;
GstWlBuffer *self = GST_WL_BUFFER (gobject);
GST_TRACE_OBJECT (self, "finalize");
-
+#ifdef GST_WLSINK_ENHANCEMENT
+ if (self->tsurface)
+ tbm_surface_destroy (self->tsurface);
+#endif
if (self->wlbuffer)
wl_buffer_destroy (self->wlbuffer);
static void
gst_wl_buffer_class_init (GstWlBufferClass * klass)
{
+ FUNCTION;
GObjectClass *object_class = (GObjectClass *) klass;
object_class->dispose = gst_wl_buffer_dispose;
static void
buffer_release (void *data, struct wl_buffer *wl_buffer)
{
+ FUNCTION;
GstWlBuffer *self = data;
-
- GST_LOG_OBJECT (self, "wl_buffer::release (GstBuffer: %p)", self->gstbuffer);
+ GST_LOG_OBJECT (self, "wl_buffer(%p)::release (GstBuffer: %p)", wl_buffer,
+ self->gstbuffer);
self->used_by_compositor = FALSE;
/* unref should be last, because it may end up destroying the GstWlBuffer */
gst_buffer_unref (self->gstbuffer);
+
}
static const struct wl_buffer_listener buffer_listener = {
static void
gstbuffer_disposed (GstWlBuffer * self)
{
+ FUNCTION;
g_assert (!self->used_by_compositor);
self->gstbuffer = NULL;
gst_buffer_add_wl_buffer (GstBuffer * gstbuffer, struct wl_buffer *wlbuffer,
GstWlDisplay * display)
{
+ FUNCTION;
GstWlBuffer *self;
self = g_object_new (GST_TYPE_WL_BUFFER, NULL);
self->gstbuffer = gstbuffer;
self->wlbuffer = wlbuffer;
self->display = display;
+#ifdef GST_WLSINK_ENHANCEMENT
+ if (display->tsurface)
+ self->tsurface = display->tsurface;
+ else
+ self->tsurface = NULL;
+ GST_INFO ("self->tsurface(%p)", self->tsurface);
+#endif
- gst_wl_display_register_buffer (self->display, self);
+ gst_wl_display_register_buffer (self->display, self); //register GstWlBuffer
wl_buffer_add_listener (self->wlbuffer, &buffer_listener, self);
+#ifdef GST_WLSINK_ENHANCEMENT //need to contribute to upstream !!
+ wl_proxy_set_queue ((struct wl_proxy *) self->wlbuffer, self->display->queue);
+#endif
gst_mini_object_set_qdata ((GstMiniObject *) gstbuffer,
gst_wl_buffer_qdata_quark (), self, (GDestroyNotify) gstbuffer_disposed);
+ GST_INFO ("GstWlBuffer (%p)", self);
return self;
}
GstWlBuffer *
gst_buffer_get_wl_buffer (GstBuffer * gstbuffer)
{
+ FUNCTION;
return gst_mini_object_get_qdata ((GstMiniObject *) gstbuffer,
gst_wl_buffer_qdata_quark ());
}
void
gst_wl_buffer_force_release_and_unref (GstWlBuffer * self)
{
+ FUNCTION;
/* Force a buffer release.
* At this point, the GstWlDisplay has killed its event loop,
* so we don't need to worry about buffer_release() being called
wl_buffer_destroy (self->wlbuffer);
self->wlbuffer = NULL;
self->display = NULL;
-
+#ifdef GST_WLSINK_ENHANCEMENT
+ GST_INFO ("self->tsurface(%p)", self->tsurface);
+ if (self->tsurface)
+ tbm_surface_destroy (self->tsurface);
+#endif
/* remove the reference that the caller (GstWlDisplay) owns */
g_object_unref (self);
}
void
gst_wl_buffer_attach (GstWlBuffer * self, struct wl_surface *surface)
{
+ FUNCTION;
g_return_if_fail (self->used_by_compositor == FALSE);
wl_surface_attach (surface, self->wlbuffer, 0, 0);
#include "wldisplay.h"
G_BEGIN_DECLS
-
#define GST_TYPE_WL_BUFFER (gst_wl_buffer_get_type ())
#define GST_WL_BUFFER(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), GST_TYPE_WL_BUFFER, GstWlBuffer))
#define GST_IS_WL_BUFFER(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), GST_TYPE_WL_BUFFER))
#define GST_WL_BUFFER_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), GST_TYPE_WL_BUFFER, GstWlBufferClass))
#define GST_IS_WL_BUFFER_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), GST_TYPE_WL_BUFFER))
#define GST_WL_BUFFER_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), GST_TYPE_WL_BUFFER, GstWlBufferClass))
-
typedef struct _GstWlBuffer GstWlBuffer;
typedef struct _GstWlBufferClass GstWlBufferClass;
{
GObject parent_instance;
- struct wl_buffer * wlbuffer;
+ struct wl_buffer *wlbuffer;
GstBuffer *gstbuffer;
GstWlDisplay *display;
gboolean used_by_compositor;
+
+#ifdef GST_WLSINK_ENHANCEMENT
+ tbm_surface_h tsurface;
+#endif
};
struct _GstWlBufferClass
GType gst_wl_buffer_get_type (void);
-GstWlBuffer * gst_buffer_add_wl_buffer (GstBuffer * gstbuffer,
- struct wl_buffer * wlbuffer, GstWlDisplay * display);
-GstWlBuffer * gst_buffer_get_wl_buffer (GstBuffer * gstbuffer);
+GstWlBuffer *gst_buffer_add_wl_buffer (GstBuffer * gstbuffer,
+ struct wl_buffer *wlbuffer, GstWlDisplay * display);
+GstWlBuffer *gst_buffer_get_wl_buffer (GstBuffer * gstbuffer);
void gst_wl_buffer_force_release_and_unref (GstWlBuffer * self);
void gst_wl_buffer_attach (GstWlBuffer * self, struct wl_surface *surface);
G_END_DECLS
-
#endif /* __GST_WL_BUFFER_H__ */
#include "wlbuffer.h"
#include <errno.h>
+#ifdef GST_WLSINK_ENHANCEMENT
+#include <fcntl.h>
+#include <unistd.h>
+#include <xf86drm.h>
+#include <string.h>
+#include <stdlib.h>
+
+#define TBM_BO_MAX_IDX 6
+
+static void
+handle_tizen_video_format (void *data, struct tizen_video *tizen_video,
+ uint32_t format)
+{
+ FUNCTION;
+ GstWlDisplay *self = data;
+
+ g_return_if_fail (self != NULL);
+
+ GST_INFO ("format is %d", format);
+ g_array_append_val (self->tbm_formats, format);
+}
+
+static const struct tizen_video_listener tz_video_listener = {
+ handle_tizen_video_format
+};
+#endif
GST_DEBUG_CATEGORY_EXTERN (gstwayland_debug);
#define GST_CAT_DEFAULT gstwayland_debug
static void
gst_wl_display_class_init (GstWlDisplayClass * klass)
{
+ FUNCTION;
GObjectClass *gobject_class = G_OBJECT_CLASS (klass);
gobject_class->finalize = gst_wl_display_finalize;
}
static void
gst_wl_display_init (GstWlDisplay * self)
{
+ FUNCTION;
self->formats = g_array_new (FALSE, FALSE, sizeof (uint32_t));
+#ifdef GST_WLSINK_ENHANCEMENT
+ self->tbm_formats = g_array_new (FALSE, FALSE, sizeof (uint32_t));
+#endif
self->wl_fd_poll = gst_poll_new (TRUE);
self->buffers = g_hash_table_new (g_direct_hash, g_direct_equal);
g_mutex_init (&self->buffers_mutex);
+#ifdef GST_WLSINK_ENHANCEMENT
+ self->tbm_bo_c_idx = 0;
+ self->tbm_bo_u_idx = 0;
+ self->tbm_need_limit_idx = FALSE;
+ self->tbm_bo_max_idx = TBM_BO_MAX_IDX;
+#endif
}
static void
gst_wl_display_finalize (GObject * gobject)
{
+ FUNCTION;
GstWlDisplay *self = GST_WL_DISPLAY (gobject);
gst_poll_set_flushing (self->wl_fd_poll, TRUE);
g_hash_table_remove_all (self->buffers);
g_array_unref (self->formats);
+#ifdef GST_WLSINK_ENHANCEMENT
+ g_array_unref (self->tbm_formats);
+#endif
gst_poll_free (self->wl_fd_poll);
g_hash_table_unref (self->buffers);
g_mutex_clear (&self->buffers_mutex);
+#ifdef GST_WLSINK_ENHANCEMENT
+ if (self->USE_TBM) {
+ if (self->is_native_format == FALSE) {
+ /*in case of normal video format */
+ for (int i = 0; i < TBM_BO_NUM; i++) {
+ if (self->tbm_bo[i])
+ tbm_bo_unref (self->tbm_bo[i]);
+ self->tbm_bo[i] = NULL;
+ }
+ }
+ if (self->tbm_client) {
+ wayland_tbm_client_deinit (self->tbm_client);
+ self->tbm_client = NULL;
+ }
+ self->tbm_bufmgr = NULL;
+ }
+#endif
if (self->shm)
wl_shm_destroy (self->shm);
-
if (self->shell)
wl_shell_destroy (self->shell);
static void
sync_callback (void *data, struct wl_callback *callback, uint32_t serial)
{
+ FUNCTION;
gboolean *done = data;
*done = TRUE;
}
static gint
gst_wl_display_roundtrip (GstWlDisplay * self)
{
+ FUNCTION;
struct wl_callback *callback;
gint ret = 0;
gboolean done = FALSE;
registry_handle_global (void *data, struct wl_registry *registry,
uint32_t id, const char *interface, uint32_t version)
{
+ FUNCTION;
GstWlDisplay *self = data;
if (g_strcmp0 (interface, "wl_compositor") == 0) {
wl_shm_add_listener (self->shm, &shm_listener, self);
} else if (g_strcmp0 (interface, "wl_scaler") == 0) {
self->scaler = wl_registry_bind (registry, id, &wl_scaler_interface, 2);
+#ifdef GST_WLSINK_ENHANCEMENT
+ } else if (g_strcmp0 (interface, "tizen_policy") == 0) {
+ self->tizen_policy =
+ wl_registry_bind (registry, id, &tizen_policy_interface, 1);
+ } else if (g_strcmp0 (interface, "tizen_video") == 0) {
+ self->tizen_video =
+ wl_registry_bind (registry, id, &tizen_video_interface, version);
+ g_return_if_fail (self->tizen_video != NULL);
+ GST_INFO ("id(%d)", id);
+
+ tizen_video_add_listener (self->tizen_video, &tz_video_listener, self);
+#endif
}
}
static gpointer
gst_wl_display_thread_run (gpointer data)
{
+ FUNCTION;
GstWlDisplay *self = data;
GstPollFD pollfd = GST_POLL_FD_INIT;
GstWlDisplay *
gst_wl_display_new (const gchar * name, GError ** error)
{
+ FUNCTION;
struct wl_display *display;
display = wl_display_connect (name);
gst_wl_display_new_existing (struct wl_display * display,
gboolean take_ownership, GError ** error)
{
+ FUNCTION;
GstWlDisplay *self;
GError *err = NULL;
gint i;
VERIFY_INTERFACE_EXISTS (compositor, "wl_compositor");
VERIFY_INTERFACE_EXISTS (subcompositor, "wl_subcompositor");
VERIFY_INTERFACE_EXISTS (shell, "wl_shell");
+#ifdef GST_WLSINK_ENHANCEMENT
+ VERIFY_INTERFACE_EXISTS (tizen_video, "tizen_video");
+ self->tbm_client = wayland_tbm_client_init (self->display);
+ if (!self->tbm_client) {
+ *error = g_error_new (g_quark_from_static_string ("GstWlDisplay"), 0,
+ "Error initializing wayland-tbm");
+ g_object_unref (self);
+ return NULL;
+ }
+ GST_INFO ("tbm_client(%p)", self->tbm_client);
+#endif
VERIFY_INTERFACE_EXISTS (shm, "wl_shm");
VERIFY_INTERFACE_EXISTS (scaler, "wl_scaler");
void
gst_wl_display_register_buffer (GstWlDisplay * self, gpointer buf)
{
+ FUNCTION;
g_assert (!self->shutting_down);
GST_TRACE_OBJECT (self, "registering GstWlBuffer %p", buf);
void
gst_wl_display_unregister_buffer (GstWlDisplay * self, gpointer buf)
{
+ FUNCTION;
GST_TRACE_OBJECT (self, "unregistering GstWlBuffer %p", buf);
g_mutex_lock (&self->buffers_mutex);
#include <gst/gst.h>
#include <wayland-client.h>
#include "scaler-client-protocol.h"
+#ifdef GST_WLSINK_ENHANCEMENT
+#include <tbm_bufmgr.h>
+#include <wayland-tbm-client.h>
+#include <tizen-extension-client-protocol.h>
+#define NV_BUF_PLANE_NUM 2 /*SN12 or ST12 has 2 plane */
+#endif
G_BEGIN_DECLS
-
#define GST_TYPE_WL_DISPLAY (gst_wl_display_get_type ())
#define GST_WL_DISPLAY(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), GST_TYPE_WL_DISPLAY, GstWlDisplay))
#define GST_IS_WL_DISPLAY(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), GST_TYPE_WL_DISPLAY))
#define GST_WL_DISPLAY_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), GST_TYPE_WL_DISPLAY, GstWlDisplayClass))
#define GST_IS_WL_DISPLAY_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), GST_TYPE_WL_DISPLAY))
#define GST_WL_DISPLAY_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), GST_TYPE_WL_DISPLAY, GstWlDisplayClass))
-
+#define FUNCTION GST_INFO ("<ENTER>")
typedef struct _GstWlDisplay GstWlDisplay;
typedef struct _GstWlDisplayClass GstWlDisplayClass;
+#define TBM_BO_NUM 20
+
struct _GstWlDisplay
{
GObject parent_instance;
struct wl_shm *shm;
struct wl_scaler *scaler;
GArray *formats;
-
+#ifdef GST_WLSINK_ENHANCEMENT
+ GArray *tbm_formats;
+#endif
/* private */
gboolean own_display;
GThread *thread;
GMutex buffers_mutex;
GHashTable *buffers;
gboolean shutting_down;
+
+#ifdef GST_WLSINK_ENHANCEMENT
+ /*video output layer */
+ struct tizen_policy *tizen_policy;
+ struct tizen_video *tizen_video;
+
+ struct wayland_tbm_client *tbm_client;
+ tbm_bufmgr tbm_bufmgr;
+ tbm_bo tbm_bo[TBM_BO_NUM];
+ int tbm_bo_c_idx;
+ int tbm_bo_u_idx;
+ gboolean tbm_need_limit_idx;
+ int tbm_bo_max_idx;
+ tbm_surface_h tsurface;
+ gboolean USE_TBM;
+
+ gboolean is_native_format; /*SN12, ST12 */
+ void *bo[NV_BUF_PLANE_NUM];
+ int plane_size[NV_BUF_PLANE_NUM];
+ int stride_width[NV_BUF_PLANE_NUM];
+ int stride_height[NV_BUF_PLANE_NUM];
+ int native_video_size;
+#endif
+
+#if 1
+ gboolean need_shell_surface;
+ gboolean use_parent_wl_surface;
+#endif
};
struct _GstWlDisplayClass
GType gst_wl_display_get_type (void);
GstWlDisplay *gst_wl_display_new (const gchar * name, GError ** error);
-GstWlDisplay *gst_wl_display_new_existing (struct wl_display * display,
+GstWlDisplay *gst_wl_display_new_existing (struct wl_display *display,
gboolean take_ownership, GError ** error);
/* see wlbuffer.c for explanation */
void gst_wl_display_unregister_buffer (GstWlDisplay * self, gpointer buf);
G_END_DECLS
-
#endif /* __GST_WL_DISPLAY_H__ */
#include <unistd.h>
#include <sys/mman.h>
#include <sys/types.h>
+//#define DUMP_BUFFER
+#ifdef DUMP_BUFFER
+int dump_cnt = 0;
+int _write_rawdata (const char *file, const void *data, unsigned int size);
+#endif
GST_DEBUG_CATEGORY_EXTERN (gstwayland_debug);
#define GST_CAT_DEFAULT gstwayland_debug
gst_wl_shm_allocator_alloc (GstAllocator * allocator, gsize size,
GstAllocationParams * params)
{
+ FUNCTION;
GstWlShmAllocator *self = GST_WL_SHM_ALLOCATOR (allocator);
char filename[1024];
static int init = 0;
int fd;
+ int idx;
gpointer data;
GstWlShmMemory *mem;
+#ifdef GST_WLSINK_ENHANCEMENT
+ if (self->display->USE_TBM) {
+ tbm_bo_handle virtual_addr;
+ if (self->display->tbm_need_limit_idx
+ && self->display->tbm_bo_c_idx == self->display->tbm_bo_max_idx)
+ self->display->tbm_bo_c_idx = 0;
+
+ idx = self->display->tbm_bo_c_idx++;
+
+ self->display->tbm_bufmgr =
+ wayland_tbm_client_get_bufmgr (self->display->tbm_client);
+ g_return_if_fail (self->display->tbm_bufmgr != NULL);
+
+ self->display->tbm_bo[idx] =
+ tbm_bo_alloc (self->display->tbm_bufmgr, size, TBM_BO_DEFAULT);
+ if (!self->display->tbm_bo[idx]) {
+ GST_ERROR_OBJECT (self, "alloc tbm bo(size:%d) failed: %s", size,
+ strerror (errno));
+ return FALSE;
+ }
+ GST_INFO ("display->tbm_bo[%d]=(%p)", idx, self->display->tbm_bo[idx]);
+ virtual_addr.ptr = NULL;
+ virtual_addr =
+ tbm_bo_get_handle (self->display->tbm_bo[idx], TBM_DEVICE_CPU);
+ if (!virtual_addr.ptr) {
+ GST_ERROR_OBJECT (self, "get tbm bo handle failed: %s", strerror (errno));
+ tbm_bo_unref (self->display->tbm_bo[idx]);
+ self->display->tbm_bo[idx] = NULL;
+ self->display->tbm_bo_c_idx--;
+ return FALSE;
+ }
+
+ mem = g_slice_new0 (GstWlShmMemory);
+ gst_memory_init ((GstMemory *) mem, GST_MEMORY_FLAG_NO_SHARE, allocator,
+ NULL, size, 0, 0, size);
+ mem->data = virtual_addr.ptr;
+ GST_INFO ("mem(%p) mem->data(%p) virtual_addr.ptr(%p) size(%d)", mem,
+ mem->data, virtual_addr.ptr, size);
+
+ return (GstMemory *) mem;
+
+ } else { /* USE SHM */
+ /* TODO: make use of the allocation params, if necessary */
+ GST_ERROR ("1");
+ /* allocate shm pool */
+ snprintf (filename, 1024, "%s/%s-%d-%s", g_get_user_runtime_dir (),
+ "wayland-shm", init++, "XXXXXX");
+
+ fd = g_mkstemp (filename);
+ if (fd < 0) {
+ GST_ERROR_OBJECT (self, "opening temp file %s failed: %s", filename,
+ strerror (errno));
+ return NULL;
+ }
+ if (ftruncate (fd, size) < 0) {
+ GST_ERROR_OBJECT (self, "ftruncate failed: %s", strerror (errno));
+ close (fd);
+ return NULL;
+ }
+
+ data = mmap (NULL, size, PROT_READ | PROT_WRITE, MAP_SHARED, fd, 0);
+ if (data == MAP_FAILED) {
+ GST_ERROR_OBJECT (self, "mmap failed: %s", strerror (errno));
+ close (fd);
+ return NULL;
+ }
+
+ unlink (filename);
+
+ mem = g_slice_new0 (GstWlShmMemory);
+ gst_memory_init ((GstMemory *) mem, GST_MEMORY_FLAG_NO_SHARE, allocator,
+ NULL, size, 0, 0, size);
+ mem->data = data;
+ mem->fd = fd;
+
+ return (GstMemory *) mem;
+ }
+
+#else /* open source */
/* TODO: make use of the allocation params, if necessary */
/* allocate shm pool */
mem->fd = fd;
return (GstMemory *) mem;
+#endif
}
static void
gst_wl_shm_allocator_free (GstAllocator * allocator, GstMemory * memory)
{
+ FUNCTION;
GstWlShmMemory *shm_mem = (GstWlShmMemory *) memory;
if (shm_mem->fd != -1)
static gpointer
gst_wl_shm_mem_map (GstMemory * mem, gsize maxsize, GstMapFlags flags)
{
+ FUNCTION;
return ((GstWlShmMemory *) mem)->data;
}
static void
gst_wl_shm_allocator_class_init (GstWlShmAllocatorClass * klass)
{
+ FUNCTION;
GstAllocatorClass *alloc_class = (GstAllocatorClass *) klass;
alloc_class->alloc = GST_DEBUG_FUNCPTR (gst_wl_shm_allocator_alloc);
static void
gst_wl_shm_allocator_init (GstWlShmAllocator * self)
{
+ FUNCTION;
self->parent_instance.mem_type = GST_ALLOCATOR_WL_SHM;
self->parent_instance.mem_map = gst_wl_shm_mem_map;
self->parent_instance.mem_unmap = gst_wl_shm_mem_unmap;
void
gst_wl_shm_allocator_register (void)
{
+ FUNCTION;
gst_allocator_register (GST_ALLOCATOR_WL_SHM,
g_object_new (GST_TYPE_WL_SHM_ALLOCATOR, NULL));
}
GstAllocator *
gst_wl_shm_allocator_get (void)
{
+ FUNCTION;
return gst_allocator_find (GST_ALLOCATOR_WL_SHM);
}
gboolean
gst_is_wl_shm_memory (GstMemory * mem)
{
+ FUNCTION;
return gst_memory_is_type (mem, GST_ALLOCATOR_WL_SHM);
}
gst_wl_shm_memory_construct_wl_buffer (GstMemory * mem, GstWlDisplay * display,
const GstVideoInfo * info)
{
+ FUNCTION;
GstWlShmMemory *shm_mem = (GstWlShmMemory *) mem;
gint width, height, stride;
gsize size;
struct wl_shm_pool *wl_pool;
struct wl_buffer *wbuffer;
+#ifdef GST_WLSINK_ENHANCEMENT
+ if (display->USE_TBM) {
+ tbm_bo_handle virtual_addr;
+ tbm_surface_info_s ts_info;
+ int num_bo;
+ void *data;
+
+ if (display->is_native_format == TRUE) {
+ width = GST_VIDEO_INFO_WIDTH (info);
+ height = GST_VIDEO_INFO_HEIGHT (info);
+ size = display->native_video_size;
+ format = gst_video_format_to_wl_tbm_format (GST_VIDEO_INFO_FORMAT (info));
+ GST_INFO ("format %s, width(%d), height(%d), size(%d)",
+ gst_wl_tbm_format_to_string (format), width, height, size);
+
+#ifdef DUMP_BUFFER
+ virtual_addr = tbm_bo_get_handle (display->bo[0], TBM_DEVICE_CPU);
+ if (!virtual_addr.ptr) {
+ GST_ERROR ("get tbm bo handle failed: %s", strerror (errno));
+ return FALSE;
+ }
+ data = virtual_addr.ptr;
+ int ret;
+ char file_name[128];
+ if (dump_cnt < 60) {
+ sprintf (file_name, "/home/owner/WLSINK_OUT_DUMP_%2.2d.dump",
+ dump_cnt++);
+ ret = _write_rawdata (file_name, virtual_addr.ptr, size);
+ if (ret) {
+ GST_ERROR ("_write_rawdata() failed");
+ }
+ }
+#endif
+ GST_DEBUG ("TBM bo %p %p %p", display->bo[0], display->bo[1], 0);
+ ts_info.width = width;
+ ts_info.height = height;
+ ts_info.format = format;
+ ts_info.bpp = tbm_surface_internal_get_bpp (ts_info.format);
+ ts_info.num_planes = tbm_surface_internal_get_num_planes (ts_info.format);
+ GST_DEBUG
+ ("ts_info.width(%d) height(%d) format(%d) bpp(%d) num_planes(%d)",
+ ts_info.width, ts_info.height, gst_wl_tbm_format_to_string (format),
+ ts_info.bpp, ts_info.num_planes);
+
+ ts_info.planes[0].stride = display->stride_width[0];
+ ts_info.planes[1].stride = display->stride_width[1];
+ ts_info.planes[0].offset = 0;
+ ts_info.planes[1].offset = (display->bo[1]) ? 0 : display->plane_size[0];
+ num_bo = (display->bo[1]) ? 2 : 1;
+ GST_INFO ("num_bo(%d)", num_bo);
+ display->tsurface =
+ tbm_surface_internal_create_with_bos (&ts_info, display->bo, num_bo);
+ GST_INFO ("display->tsurface(%p)", display->tsurface);
+ GST_INFO ("tbm_client(%p),tsurface(%p)", display->tbm_client,
+ display->tsurface);
+ wbuffer =
+ wayland_tbm_client_create_buffer (display->tbm_client,
+ display->tsurface);
+ } else {
+ int idx;
+ if (display->tbm_need_limit_idx
+ && display->tbm_bo_u_idx == display->tbm_bo_max_idx)
+ display->tbm_bo_u_idx = 0;
+
+ idx = display->tbm_bo_u_idx++;
+ width = GST_VIDEO_INFO_WIDTH (info);
+ height = GST_VIDEO_INFO_HEIGHT (info);
+ stride = GST_VIDEO_INFO_PLANE_STRIDE (info, 0);
+ size = GST_VIDEO_INFO_SIZE (info);
+
+ format = gst_video_format_to_wl_tbm_format (GST_VIDEO_INFO_FORMAT (info));
+ g_return_val_if_fail (gst_is_wl_shm_memory (mem), NULL);
+ g_return_val_if_fail (size <= mem->size, NULL);
+ g_return_val_if_fail (shm_mem->fd != -1, NULL);
+
+ GST_DEBUG_OBJECT (mem->allocator, "Creating wl_buffer of size %"
+ G_GSSIZE_FORMAT " (%d x %d, stride %d), format %s", size, width,
+ height, stride, gst_wl_tbm_format_to_string (format));
+
+#ifdef DUMP_BUFFER
+ virtual_addr = tbm_bo_get_handle (display->tbm_bo[idx], TBM_DEVICE_CPU);
+ if (!virtual_addr.ptr) {
+ GST_ERROR ("get tbm bo handle failed: %s", strerror (errno));
+ return FALSE;
+ }
+ data = virtual_addr.ptr;
+ int ret;
+ char file_name[128];
+ GST_ERROR ("DUMP %d ", dump_cnt);
+// if (dump_cnt < 60) {
+ sprintf (file_name, "/home/owner/WLSINK_OUT_DUMP_%2.2d.dump", dump_cnt++);
+ ret = _write_rawdata (file_name, virtual_addr.ptr, size);
+ if (ret) {
+ GST_ERROR ("_write_rawdata() failed");
+ }
+// }
+#endif
+ ts_info.width = width;
+ ts_info.height = height;
+ ts_info.format = format;
+ ts_info.bpp = tbm_surface_internal_get_bpp (ts_info.format);
+ ts_info.num_planes = tbm_surface_internal_get_num_planes (ts_info.format);
+ ts_info.planes[0].stride = GST_VIDEO_INFO_PLANE_STRIDE (info, 0);
+ ts_info.planes[1].stride = GST_VIDEO_INFO_PLANE_STRIDE (info, 1);
+ ts_info.planes[2].stride = GST_VIDEO_INFO_PLANE_STRIDE (info, 2);
+ ts_info.planes[0].offset = GST_VIDEO_INFO_PLANE_OFFSET (info, 0);
+ ts_info.planes[1].offset = GST_VIDEO_INFO_PLANE_OFFSET (info, 1);
+ ts_info.planes[2].offset = GST_VIDEO_INFO_PLANE_OFFSET (info, 2);
+
+ GST_INFO ("display->tbm_bo (%p)", display->tbm_bo[idx]);
+
+ display->tsurface =
+ tbm_surface_internal_create_with_bos (&ts_info, &display->tbm_bo[idx],
+ 1);
+ wbuffer =
+ wayland_tbm_client_create_buffer (display->tbm_client,
+ display->tsurface);
+ }
+ GST_INFO ("wayland_tbm_client_create_buffer create wl_buffer %p", wbuffer);
+
+ return wbuffer;
+
+ } else { /* USE SHM */
+ width = GST_VIDEO_INFO_WIDTH (info);
+ height = GST_VIDEO_INFO_HEIGHT (info);
+ stride = GST_VIDEO_INFO_PLANE_STRIDE (info, 0);
+ size = GST_VIDEO_INFO_SIZE (info);
+ format = gst_video_format_to_wl_shm_format (GST_VIDEO_INFO_FORMAT (info));
+ g_return_val_if_fail (gst_is_wl_shm_memory (mem), NULL);
+ g_return_val_if_fail (size <= mem->size, NULL);
+ g_return_val_if_fail (shm_mem->fd != -1, NULL);
+
+ GST_DEBUG_OBJECT (mem->allocator, "Creating wl_buffer of size %"
+ G_GSSIZE_FORMAT " (%d x %d, stride %d), format %s", size, width, height,
+ stride, gst_wl_shm_format_to_string (format));
+
+ wl_pool = wl_shm_create_pool (display->shm, shm_mem->fd, mem->size);
+ wbuffer =
+ wl_shm_pool_create_buffer (wl_pool, 0, width, height, stride, format);
+
+ close (shm_mem->fd);
+ shm_mem->fd = -1;
+ wl_shm_pool_destroy (wl_pool);
+
+ return wbuffer;
+ }
+#else /* open source */
width = GST_VIDEO_INFO_WIDTH (info);
height = GST_VIDEO_INFO_HEIGHT (info);
stride = GST_VIDEO_INFO_PLANE_STRIDE (info, 0);
size = GST_VIDEO_INFO_SIZE (info);
format = gst_video_format_to_wl_shm_format (GST_VIDEO_INFO_FORMAT (info));
-
g_return_val_if_fail (gst_is_wl_shm_memory (mem), NULL);
g_return_val_if_fail (size <= mem->size, NULL);
g_return_val_if_fail (shm_mem->fd != -1, NULL);
wl_shm_pool_destroy (wl_pool);
return wbuffer;
+#endif
+}
+
+#ifdef DUMP_BUFFER
+int
+_write_rawdata (const char *file, const void *data, unsigned int size)
+{
+ FILE *fp;
+
+ fp = fopen (file, "wb");
+ if (fp == NULL)
+ return -1;
+
+ fwrite ((char *) data, sizeof (char), size, fp);
+ fclose (fp);
+
+ return 0;
}
+#endif
#include "wldisplay.h"
G_BEGIN_DECLS
-
#define GST_TYPE_WL_SHM_ALLOCATOR (gst_wl_shm_allocator_get_type ())
#define GST_WL_SHM_ALLOCATOR(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), GST_TYPE_WL_SHM_ALLOCATOR, GstWlShmAllocator))
#define GST_IS_WL_SHM_ALLOCATOR(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), GST_TYPE_WL_SHM_ALLOCATOR))
#define GST_WL_SHM_ALLOCATOR_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), GST_TYPE_WL_SHM_ALLOCATOR, GstWlShmAllocatorClass))
#define GST_IS_WL_SHM_ALLOCATOR_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), GST_TYPE_WL_SHM_ALLOCATOR))
#define GST_WL_SHM_ALLOCATOR_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), GST_TYPE_WL_SHM_ALLOCATOR, GstWlShmAllocatorClass))
-
#define GST_ALLOCATOR_WL_SHM "wl_shm"
-
typedef struct _GstWlShmMemory GstWlShmMemory;
typedef struct _GstWlShmAllocator GstWlShmAllocator;
typedef struct _GstWlShmAllocatorClass GstWlShmAllocatorClass;
struct _GstWlShmAllocator
{
GstAllocator parent_instance;
+#ifdef GST_WLSINK_ENHANCEMENT
+ GstWlDisplay *display;
+#endif
};
struct _GstWlShmAllocatorClass
GType gst_wl_shm_allocator_get_type (void);
void gst_wl_shm_allocator_register (void);
-GstAllocator * gst_wl_shm_allocator_get (void);
+GstAllocator *gst_wl_shm_allocator_get (void);
gboolean gst_is_wl_shm_memory (GstMemory * mem);
-struct wl_buffer * gst_wl_shm_memory_construct_wl_buffer (GstMemory * mem,
+struct wl_buffer *gst_wl_shm_memory_construct_wl_buffer (GstMemory * mem,
GstWlDisplay * display, const GstVideoInfo * info);
G_END_DECLS
-
#endif /* __GST_WL_SHM_ALLOCATOR_H__ */
* Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
* Boston, MA 02110-1301 USA.
*/
-
#ifdef HAVE_CONFIG_H
#include <config.h>
#endif
GST_DEBUG_CATEGORY_EXTERN (gstwayland_debug);
#define GST_CAT_DEFAULT gstwayland_debug
-
+#define FUNCTION GST_INFO ("<ENTER>")
typedef struct
{
enum wl_shm_format wl_format;
enum wl_shm_format
gst_video_format_to_wl_shm_format (GstVideoFormat format)
{
+ FUNCTION;
guint i;
for (i = 0; i < G_N_ELEMENTS (formats); i++)
GstVideoFormat
gst_wl_shm_format_to_video_format (enum wl_shm_format wl_format)
{
+ FUNCTION;
guint i;
for (i = 0; i < G_N_ELEMENTS (formats); i++)
const gchar *
gst_wl_shm_format_to_string (enum wl_shm_format wl_format)
{
+ FUNCTION;
return gst_video_format_to_string
(gst_wl_shm_format_to_video_format (wl_format));
}
* Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
* Boston, MA 02110-1301 USA.
*/
-
#ifndef __GST_WL_VIDEO_FORMAT_H__
#define __GST_WL_VIDEO_FORMAT_H__
#include <gst/video/video.h>
G_BEGIN_DECLS
-
-enum wl_shm_format gst_video_format_to_wl_shm_format (GstVideoFormat format);
+ enum wl_shm_format gst_video_format_to_wl_shm_format (GstVideoFormat
+ format);
GstVideoFormat gst_wl_shm_format_to_video_format (enum wl_shm_format wl_format);
const gchar *gst_wl_shm_format_to_string (enum wl_shm_format wl_format);
G_END_DECLS
-
#endif
static void
gst_wl_window_class_init (GstWlWindowClass * klass)
{
+ FUNCTION;
GObjectClass *gobject_class = G_OBJECT_CLASS (klass);
gobject_class->finalize = gst_wl_window_finalize;
}
static void
gst_wl_window_finalize (GObject * gobject)
{
+ FUNCTION;
GstWlWindow *self = GST_WL_WINDOW (gobject);
+#ifdef GST_WLSINK_ENHANCEMENT
+ if (self->video_object)
+ tizen_video_object_destroy (self->video_object);
+#endif
+
if (self->shell_surface) {
wl_shell_surface_destroy (self->shell_surface);
}
}
static GstWlWindow *
-gst_wl_window_new_internal (GstWlDisplay * display)
+gst_wl_window_new_internal (GstWlDisplay * display, struct wl_surface *parent)
{
+ FUNCTION;
GstWlWindow *window;
GstVideoInfo info;
GstBuffer *buf;
wl_proxy_set_queue ((struct wl_proxy *) window->video_surface,
display->queue);
+#if 1 /* create shell_surface here for enlightenment */
+ /* go toplevel */
+ if (display->need_shell_surface) {
+ window->shell_surface = wl_shell_get_shell_surface (display->shell,
+ window->area_surface);
+ }
+ if (display->use_parent_wl_surface && parent != NULL) {
+ window->area_subsurface =
+ wl_subcompositor_get_subsurface (display->subcompositor,
+ window->area_surface, parent);
+ wl_subsurface_set_desync (window->area_subsurface);
+ }
+#endif
+
/* embed video_surface in area_surface */
window->video_subsurface =
wl_subcompositor_get_subsurface (display->subcompositor,
#endif
1, 1);
+#ifdef GST_WLSINK_ENHANCEMENT
+ if (window->display->USE_TBM) {
+ /* Inform enlightenment of surface which render video */
+ window->video_object =
+ tizen_video_get_object (display->tizen_video, window->video_surface);
+ }
+#else /* open source */
buf = gst_buffer_new_allocate (gst_wl_shm_allocator_get (), info.size, NULL);
gst_buffer_map (buf, &mapinfo, GST_MAP_WRITE);
*((guint32 *) mapinfo.data) = 0; /* paint it black */
/* at this point, the GstWlBuffer keeps the buffer
* alive and will free it on wl_buffer::release */
gst_buffer_unref (buf);
+#endif
/* do not accept input */
region = wl_compositor_create_region (display->compositor);
GstWlWindow *
gst_wl_window_new_toplevel (GstWlDisplay * display, const GstVideoInfo * info)
{
+ FUNCTION;
GstWlWindow *window;
gint width;
- window = gst_wl_window_new_internal (display);
+/* not create shell_surface here for enlightenment */
+ display->need_shell_surface = TRUE;
+
+ window = gst_wl_window_new_internal (display, NULL);
+#if 0 //GST_WLSINK_ENHANCEMENT
/* go toplevel */
window->shell_surface = wl_shell_get_shell_surface (display->shell,
window->area_surface);
-
+#endif
if (window->shell_surface) {
wl_shell_surface_add_listener (window->shell_surface,
&shell_surface_listener, window);
gst_wl_window_new_in_surface (GstWlDisplay * display,
struct wl_surface * parent)
{
+ FUNCTION;
GstWlWindow *window;
- window = gst_wl_window_new_internal (display);
+ display->use_parent_wl_surface = TRUE;
+ window = gst_wl_window_new_internal (display, parent);
+
+#if 0
/* embed in parent */
window->area_subsurface =
wl_subcompositor_get_subsurface (display->subcompositor,
window->area_surface, parent);
wl_subsurface_set_desync (window->area_subsurface);
+#endif
+
+#ifdef GST_WLSINK_ENHANCEMENT
+ if (display->USE_TBM) {
+ /*Area surface from App need to be under parent surface */
+ if (display->tizen_policy)
+ tizen_policy_place_subsurface_below_parent (display->tizen_policy,
+ window->area_subsurface);
+ wl_surface_commit (parent);
+ }
+#endif
return window;
}
GstWlDisplay *
gst_wl_window_get_display (GstWlWindow * window)
{
+ FUNCTION;
g_return_val_if_fail (window != NULL, NULL);
return g_object_ref (window->display);
struct wl_surface *
gst_wl_window_get_wl_surface (GstWlWindow * window)
{
+ FUNCTION;
g_return_val_if_fail (window != NULL, NULL);
return window->video_surface;
gboolean
gst_wl_window_is_toplevel (GstWlWindow * window)
{
+ FUNCTION;
g_return_val_if_fail (window != NULL, FALSE);
return (window->shell_surface != NULL);
static void
gst_wl_window_resize_video_surface (GstWlWindow * window, gboolean commit)
{
+ FUNCTION;
GstVideoRectangle src = { 0, };
GstVideoRectangle res;
gst_wl_window_render (GstWlWindow * window, GstWlBuffer * buffer,
const GstVideoInfo * info)
{
+ FUNCTION;
if (G_UNLIKELY (info)) {
window->video_width =
gst_util_uint64_scale_int_round (info->width, info->par_n, info->par_d);
else
wl_surface_attach (window->video_surface, NULL, 0, 0);
+ /*Wayland-compositor will try to render damage area which need to be updated */
wl_surface_damage (window->video_surface, 0, 0, window->surface_width,
window->surface_height);
+ /* wl_surface_commit change surface state, if wl_buffer is not attached newly, then surface is not changed */
wl_surface_commit (window->video_surface);
if (G_UNLIKELY (info)) {
gst_wl_window_set_render_rectangle (GstWlWindow * window, gint x, gint y,
gint w, gint h)
{
+ FUNCTION;
g_return_if_fail (window != NULL);
-
+#ifdef GST_WLSINK_ENHANCEMENT
+ if (window->render_rectangle.x == x && window->render_rectangle.y == y
+ && window->render_rectangle.w == w && window->render_rectangle.h == h) {
+ GST_DEBUG ("but the values are same. skip");
+ return;
+ }
+#endif
window->render_rectangle.x = x;
window->render_rectangle.y = y;
window->render_rectangle.w = w;
#include <gst/video/video.h>
G_BEGIN_DECLS
-
#define GST_TYPE_WL_WINDOW (gst_wl_window_get_type ())
#define GST_WL_WINDOW(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), GST_TYPE_WL_WINDOW, GstWlWindow))
#define GST_IS_WL_WINDOW(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), GST_TYPE_WL_WINDOW))
#define GST_WL_WINDOW_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), GST_TYPE_WL_WINDOW, GstWlWindowClass))
#define GST_IS_WL_WINDOW_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), GST_TYPE_WL_WINDOW))
#define GST_WL_WINDOW_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), GST_TYPE_WL_WINDOW, GstWlWindowClass))
-
typedef struct _GstWlWindow GstWlWindow;
typedef struct _GstWlWindowClass GstWlWindowClass;
struct wl_subsurface *video_subsurface;
struct wl_viewport *video_viewport;
struct wl_shell_surface *shell_surface;
+#ifdef GST_WLSINK_ENHANCEMENT
+ struct tizen_video_object *video_object;
+#endif
/* the size and position of the area_(sub)surface */
GstVideoRectangle render_rectangle;
GType gst_wl_window_get_type (void);
GstWlWindow *gst_wl_window_new_toplevel (GstWlDisplay * display,
- const GstVideoInfo * info);
+ const GstVideoInfo * info);
GstWlWindow *gst_wl_window_new_in_surface (GstWlDisplay * display,
- struct wl_surface * parent);
+ struct wl_surface *parent);
GstWlDisplay *gst_wl_window_get_display (GstWlWindow * window);
struct wl_surface *gst_wl_window_get_wl_surface (GstWlWindow * window);
-gboolean gst_wl_window_is_toplevel (GstWlWindow *window);
+gboolean gst_wl_window_is_toplevel (GstWlWindow * window);
void gst_wl_window_render (GstWlWindow * window, GstWlBuffer * buffer,
- const GstVideoInfo * info);
+ const GstVideoInfo * info);
void gst_wl_window_set_render_rectangle (GstWlWindow * window, gint x, gint y,
- gint w, gint h);
+ gint w, gint h);
G_END_DECLS
-
#endif /* __GST_WL_WINDOW_H__ */
%if %{with wayland}
%{_libdir}/libgstwayland-%{gst_branch}.so.0*
-#%{_libdir}/gstreamer-%{gst_branch}/libgstwaylandsink.so
+%{_libdir}/gstreamer-%{gst_branch}/libgstwaylandsink.so
%endif
%{_libdir}/libgstphotography-%{gst_branch}.so.0*