GstWaylandSink *sink = GST_WAYLAND_SINK (bsink);
GstStructure *config;
guint size, min_bufs, max_bufs;
+
#ifdef TIZEN_FEATURE_WLSINK_ENHANCEMENT
gboolean need_pool;
GstCaps *caps;
if (sink->USE_TBM) {
if (sink->display->is_native_format == TRUE)
- return TRUE;
+ return FALSE;
gst_query_parse_allocation (query, &caps, &need_pool);
gst_wl_window_render (sink->window, wlbuffer, info);
}
+
+static gboolean
+gst_wayland_sink_has_wlbuffer (GstWaylandSink * sink, GstBuffer * buffer)
+{
+ GstWlBuffer *gstwlbuffer;
+ FUNCTION;
+ g_return_val_if_fail (sink != NULL, FALSE);
+ g_return_val_if_fail (buffer != NULL, FALSE);
+
+ gstwlbuffer = gst_buffer_get_wl_buffer (buffer);
+ if (gstwlbuffer && gstwlbuffer->display == sink->display
+ && !gst_wayland_sink_is_gapless (sink)
+ && !sink->request_camera_flush_buf) {
+ /* gstbuffer has wlbuffer */
+ /* e.g) last_buffer, buffer is created by previous plugin or waylandsink with BufferPool */
+ GST_LOG ("buffer(%p) has GstWlBuffer(%p):wlbuffer(%p)", buffer, gstwlbuffer,
+ gstwlbuffer->wlbuffer);
+ return TRUE;
+ }
+ GST_LOG ("buffer(%p) has not wlbuffer", buffer);
+ return FALSE;
+}
+
+static void
+gst_wayland_sink_no_create_wlbuffer (GstWaylandSink * sink, GstBuffer * buffer)
+{
+ GstMemory *mem;
+ FUNCTION;
+ g_return_if_fail (sink != NULL);
+ g_return_if_fail (buffer != NULL);
+
+ /* the last_buffer for flushing has wlbuffer or
+ buffer is created by previous plugins or waylandsink has wlbuffer */
+ mem = gst_buffer_peek_memory (buffer, 0);
+ if (gst_is_wl_memory (mem)) {
+ GST_LOG ("buffer(%p) is created by waylandsink has a wl_buffer, "
+ "writing directly", buffer);
+ } else {
+ GST_LOG
+ ("buffer(%p) is created by previous plugins with BufferPool has a wl_buffer, "
+ "writing directly", buffer);
+ GST_LOG ("previous plugins must manage buffer index well");
+ }
+
+ sink->to_render = buffer;
+
+ if (sink->dump_video && !sink->display->is_native_format)
+ gst_wayland_sink_dump_raw_video (sink, sink->to_render,
+ sink->display->dump_count++, sink->total_dump);
+}
+
+static void
+gst_wayland_sink_create_wlbuffer_with_wl_mem (GstWaylandSink * sink,
+ GstBuffer * buffer)
+{
+ GstMemory *mem;
+ struct wl_buffer *wbuf = NULL;
+ FUNCTION;
+ g_return_if_fail (sink != NULL);
+ g_return_if_fail (buffer != NULL);
+
+ GST_LOG ("gstbuffer(%p) is created by wayland has not wlbuffer", buffer);
+ mem = gst_buffer_peek_memory (buffer, 0);
+ 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);
+ sink->to_render = buffer;
+ }
+}
+
+static GstFlowReturn
+gst_wayland_sink_create_wlbuffer_with_previous_plugin_tbm (GstWaylandSink *
+ sink, GstBuffer * buffer)
+{
+ GstMemory *mem;
+ GstWlBuffer *wlbuffer;
+ struct wl_buffer *wbuf = NULL;
+ GstFlowReturn ret = GST_FLOW_OK;
+ FUNCTION;
+ g_return_val_if_fail (sink != NULL, GST_FLOW_ERROR);
+ g_return_val_if_fail (buffer != NULL, GST_FLOW_ERROR);
+ sink->flush_gstbuf = NULL;
+
+ GST_LOG
+ ("buffer(%p) is created by previous plugin with no BufferPool does not have a wl_buffer",
+ buffer);
+ GST_LOG ("Use native format with previous plugins TBM");
+ /* in case of native format (SN12, ST12, SR32 and S420) */
+ if (!gst_wayland_sink_get_mm_video_buf_info (sink, buffer)) {
+ return GST_FLOW_ERROR;
+ }
+
+ wlbuffer = gst_buffer_get_wl_buffer (buffer);
+ /* last_buffer from gaplasee have wlbuffer */
+ if (G_UNLIKELY (!wlbuffer) || sink->display->flush_request) {
+ mem = gst_buffer_peek_memory (buffer, 0);
+ wbuf =
+ gst_wl_shm_memory_construct_wl_buffer (mem, sink->display,
+ &sink->video_info);
+ if (G_UNLIKELY (!wbuf)) {
+ GST_ERROR ("could not create wl_buffer");
+ return GST_FLOW_ERROR;
+ }
+ if (sink->display->flush_request) {
+ sink->flush_gstbuf = gst_buffer_new ();
+ GST_LOG ("To flush, new gstBuffer(%p)", sink->flush_gstbuf);
+ gst_buffer_add_wl_buffer (sink->flush_gstbuf, wbuf, sink->display);
+ } else {
+ gst_buffer_add_wl_buffer (buffer, wbuf, sink->display);
+ }
+ }
+ return ret;
+}
+
+static GstFlowReturn
+ gst_wayland_sink_copy_input_gstbuffer_to_wl_gstbuffer_with_wl_mem
+ (GstWaylandSink * sink, GstBuffer * buffer)
+{
+ GstWlBuffer *wlbuffer;
+ GstMemory *mem;
+ GstWlShmMemory *shm_mem;
+ GstMapInfo src;
+ struct wl_buffer *wbuf = NULL;
+ GstFlowReturn ret = GST_FLOW_OK;
+ FUNCTION;
+ g_return_val_if_fail (sink != NULL, GST_FLOW_ERROR);
+ g_return_val_if_fail (buffer != NULL, GST_FLOW_ERROR);
+
+ GST_LOG ("Use normal format with wayland TBM or 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)) {
+ GST_ERROR ("failed to activate bufferpool.");
+ return GST_FLOW_ERROR;
+ }
+
+ ret = gst_buffer_pool_acquire_buffer (sink->pool, &sink->to_render, NULL);
+ if (ret != GST_FLOW_OK) {
+ GST_WARNING ("could not create buffer");
+ return ret;
+ }
+ /* 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 (sink->to_render, 0);
+ shm_mem = (GstWlShmMemory *) mem;
+ GST_LOG ("to_render(%p), shm_mem->fd(%d)", sink->to_render, shm_mem->fd);
+ wbuf =
+ gst_wl_shm_memory_construct_wl_buffer (mem, sink->display,
+ &sink->video_info);
+ if (G_UNLIKELY (!wbuf)) {
+ GST_ERROR ("could not create wl_buffer out of wl memory");
+ return GST_FLOW_ERROR;
+ }
+ wlbuffer = gst_buffer_add_wl_buffer (sink->to_render, wbuf, sink->display);
+ }
+
+ gst_buffer_map (buffer, &src, GST_MAP_READ);
+ gst_buffer_fill (sink->to_render, 0, src.data, src.size);
+ gst_buffer_unmap (buffer, &src);
+
+ return ret;
+}
+
+static GstFlowReturn
+gst_wayland_sink_create_wlbuffer (GstWaylandSink * sink, GstBuffer * buffer)
+{
+ GstMemory *mem;
+ GstFlowReturn ret = GST_FLOW_OK;
+ FUNCTION;
+ g_return_val_if_fail (sink != NULL, GST_FLOW_ERROR);
+ g_return_val_if_fail (buffer != NULL, GST_FLOW_ERROR);
+
+ sink->to_render = NULL;
+
+ if (gst_wayland_sink_has_wlbuffer (sink, buffer)) {
+ gst_wayland_sink_no_create_wlbuffer (sink, buffer);
+ } else {
+ mem = gst_buffer_peek_memory (buffer, 0);
+ if (gst_is_wl_memory (mem)) {
+ /* SHM or TBM */
+ gst_wayland_sink_create_wlbuffer_with_wl_mem (sink, buffer);
+ } else {
+ /* gstbuffer is not wl memory */
+ if (sink->USE_TBM && sink->display->is_native_format) {
+ /* Use tbm of buffer directly */
+ ret =
+ gst_wayland_sink_create_wlbuffer_with_previous_plugin_tbm (sink,
+ buffer);
+ } else {
+ /* Copy virtual addr to wayland SHM or TBM */
+ ret =
+ gst_wayland_sink_copy_input_gstbuffer_to_wl_gstbuffer_with_wl_mem
+ (sink, buffer);
+ }
+ }
+ }
+ return ret;
+}
+
+static void
+gst_wayland_sink_buffer_replace (GstWaylandSink * sink, GstBuffer * buffer)
+{
+ FUNCTION;
+ g_return_if_fail (sink != NULL);
+
+ if (sink->USE_TBM && sink->display->is_native_format) {
+ if (sink->flush_gstbuf && sink->display->flush_request) {
+ GST_LOG_OBJECT (sink, "replace last_buffer:(%p)->(%p)", sink->last_buffer,
+ sink->flush_gstbuf);
+ /* increase ref count of sink->fflush_gstbuf, decrease ref count of sink->last_buffer */
+ gst_buffer_replace (&sink->last_buffer, sink->flush_gstbuf);
+ GST_LOG_OBJECT (sink, "after gst_buffer_replace buffer %p, ref_count(%d)",
+ sink->flush_gstbuf, GST_OBJECT_REFCOUNT_VALUE (sink->flush_gstbuf));
+ /* decrease ref count of flush_buffer */
+ gst_buffer_unref (sink->flush_gstbuf);
+ } else {
+ /* normal case */
+ GST_LOG_OBJECT (sink, "replace last_buffer:(%p)->(%p)", sink->last_buffer,
+ buffer);
+ /* increase ref count of buffer decrease ref count of sink->last_buffer */
+ gst_buffer_replace (&sink->last_buffer, buffer);
+ GST_LOG_OBJECT (sink, "after gst_buffer_replace buffer %p, ref_count(%d)",
+ buffer, GST_OBJECT_REFCOUNT_VALUE (buffer));
+ }
+ } else {
+ gst_buffer_replace (&sink->last_buffer, sink->to_render);
+ GST_LOG_OBJECT (sink, "after gst_buffer_replace buffer %p, ref_count(%d)",
+ sink->to_render, GST_OBJECT_REFCOUNT_VALUE (sink->to_render));
+ }
+}
+
+static void
+gst_wayland_sink_get_window (GstWaylandSink * sink)
+{
+ g_return_if_fail (sink != NULL);
+ FUNCTION;
+
+ /* ask for window handle. Unlock render_lock while doing that because
+ * set_window_handle & friends will lock it in this context */
+ g_mutex_unlock (&sink->render_lock);
+ gst_video_overlay_prepare_window_handle (GST_VIDEO_OVERLAY (sink));
+ g_mutex_lock (&sink->render_lock);
+
+ if (!sink->window) {
+ /* if we were not provided a window, create one ourselves */
+ sink->window =
+ gst_wl_window_new_toplevel (sink->display, &sink->video_info);
+ }
+ gst_wayland_sink_update_window_geometry (sink);
+}
+
static GstFlowReturn
gst_wayland_sink_render (GstBaseSink * bsink, GstBuffer * buffer)
{
+#ifdef TIZEN_FEATURE_WLSINK_ENHANCEMENT
+
GstWaylandSink *sink = GST_WAYLAND_SINK (bsink);
- GstBuffer *to_render;
- GstBuffer *flush_gstbuf = NULL;
- GstWlBuffer *wlbuffer;
GstFlowReturn ret = GST_FLOW_OK;
FUNCTION;
g_mutex_lock (&sink->render_lock);
- GST_LOG_OBJECT (sink, "render gstbuffer %p, ref_count(%d)", buffer,
+ GST_LOG_OBJECT (sink, "input gstbuffer %p, ref_count(%d)", buffer,
GST_OBJECT_REFCOUNT_VALUE (buffer));
+ /* check overlay */
if (gst_wayland_sink_is_disabled_overlay (sink)) {
GST_LOG ("set disable_overlay, so skip");
goto done;
}
+ /* check window */
if (G_UNLIKELY (!sink->window)) {
- /* ask for window handle. Unlock render_lock while doing that because
- * set_window_handle & friends will lock it in this context */
- g_mutex_unlock (&sink->render_lock);
- gst_video_overlay_prepare_window_handle (GST_VIDEO_OVERLAY (sink));
- g_mutex_lock (&sink->render_lock);
-
- if (!sink->window) {
- /* if we were not provided a window, create one ourselves */
- sink->window =
- gst_wl_window_new_toplevel (sink->display, &sink->video_info);
- }
-#ifdef TIZEN_FEATURE_WLSINK_ENHANCEMENT
- gst_wayland_sink_update_window_geometry (sink);
-#endif
+ gst_wayland_sink_get_window (sink);
}
+ /* fakesink function for media stream callback case */
if (sink->signal_handoffs) {
GST_LOG ("g_signal_emit: hand-off ");
g_signal_emit (sink, gst_waylandsink_signals[SIGNAL_HANDOFF], 0, buffer,
&& !gst_wayland_sink_is_gapless (sink))
goto done;
-#ifndef TIZEN_FEATURE_WLSINK_ENHANCEMENT /* for tizen view_port, we don't know window size */
- /* make sure that the application has called set_render_rectangle() */
- if (G_UNLIKELY (sink->window->render_rectangle.w == 0))
- goto no_window_size;
-#endif
-#ifdef TIZEN_FEATURE_WLSINK_ENHANCEMENT
+ /* create wl_buffer */
+ ret = gst_wayland_sink_create_wlbuffer (sink, buffer);
+ if (ret != GST_FLOW_OK)
+ goto done;
- wlbuffer = gst_buffer_get_wl_buffer (buffer);
- if (G_LIKELY (wlbuffer && wlbuffer->display == sink->display)
- && !(gst_wayland_sink_is_gapless (sink))
- && !sink->request_camera_flush_buf) {
- GST_LOG_OBJECT (sink, "buffer %p has a wl_buffer from our display, " "writing directly", buffer); //buffer is from our pool and have wl_buffer
- GST_LOG ("wl_buffer (%p)", wlbuffer->wlbuffer);
- to_render = buffer;
+ /* drop double rendering */
+ if ((G_UNLIKELY (buffer == sink->last_buffer)
+ && !(sink->display->flush_request))) {
+ GST_LOG_OBJECT (sink, "Buffer already being rendered");
+ goto done;
+ }
- if (sink->dump_video)
- gst_wayland_sink_dump_raw_video (sink, to_render,
- sink->display->dump_count++, sink->total_dump);
+ /* replace last_buffer */
+ gst_wayland_sink_buffer_replace (sink, buffer);
+ /* rendering */
+ if (sink->visible) {
+ render_last_buffer (sink);
} 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); //buffer is from our pool but have not wl_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); //careat GstWlBuffer and add gstbuffer, wlbuffer, display and etc
- to_render = buffer;
- }
- } else { //buffer is not from our pool and have not wl_buffer
- 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);
-
- if (sink->USE_TBM && sink->display->is_native_format) {
- /* in case of SN12 or ST12 */
- if (!gst_wayland_sink_get_mm_video_buf_info (sink, buffer)) {
- ret = GST_FLOW_ERROR;
- goto done;
- }
-
- wlbuffer = gst_buffer_get_wl_buffer (buffer);
- /* last_buffer from gaplasee have wlbuffer */
- if (G_UNLIKELY (!wlbuffer) || sink->display->flush_request) {
- wbuf =
- gst_wl_shm_memory_construct_wl_buffer (mem, sink->display,
- &sink->video_info);
- if (G_UNLIKELY (!wbuf))
- goto no_wl_buffer;
- if (sink->display->flush_request) {
- flush_gstbuf = gst_buffer_new ();
- GST_LOG ("To flush, new gstBuffer(%p)", flush_gstbuf);
- gst_buffer_add_wl_buffer (flush_gstbuf, wbuf, sink->display);
-
- } else {
- gst_buffer_add_wl_buffer (buffer, wbuf, sink->display);
- }
- }
- } else if (sink->USE_TBM && !sink->display->is_native_format) {
-
- /* 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_LOG ("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);
- }
- }
+ GST_LOG ("skip rendering");
}
- if (sink->USE_TBM && sink->display->is_native_format) {
- if ((G_UNLIKELY (buffer == sink->last_buffer)
- && !(sink->display->flush_request))) {
- GST_LOG_OBJECT (sink, "Buffer already being rendered");
- goto done;
- }
+ if (sink->to_render) {
+ if (buffer != sink->to_render)
+ gst_buffer_unref (sink->to_render);
+ }
- if (flush_gstbuf && sink->display->flush_request) {
+ goto done;
- GST_LOG_OBJECT (sink, "replace last_buffer: (%p) -> (%p)",
- sink->last_buffer, flush_gstbuf);
- /* increase ref count of flush_gstbuf
- decrease ref count of sink->last_buffer */
- gst_buffer_replace (&sink->last_buffer, flush_gstbuf);
- GST_LOG_OBJECT (sink, "after gst_buffer_replace buffer %p, ref_count(%d)",
- flush_gstbuf, GST_OBJECT_REFCOUNT_VALUE (flush_gstbuf));
- /* decrease ref count of flush_buffer */
- gst_buffer_unref (flush_gstbuf);
+#else /* open source */
- } else { //normal case
+ GstWaylandSink *sink = GST_WAYLAND_SINK (bsink);
+ GstBuffer *to_render = NULL;
+ GstFlowReturn ret = GST_FLOW_OK;
- GST_LOG_OBJECT (sink, "replace last_buffer: (%p) -> (%p)",
- sink->last_buffer, buffer);
- /* increase ref count of buffer
- decrease ref count of sink->last_buffer */
- gst_buffer_replace (&sink->last_buffer, buffer);
- GST_LOG_OBJECT (sink, "after gst_buffer_replace buffer %p, ref_count(%d)",
- buffer, GST_OBJECT_REFCOUNT_VALUE (buffer));
- }
- if (sink->visible) {
- render_last_buffer (sink);
- } else {
- GST_LOG ("skip rendering");
- }
- goto done;
+ g_mutex_lock (&sink->render_lock);
- } 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);
+ if (G_UNLIKELY (!sink->window)) {
+ /* ask for window handle. Unlock render_lock while doing that because
+ * set_window_handle & friends will lock it in this context */
+ g_mutex_unlock (&sink->render_lock);
+ gst_video_overlay_prepare_window_handle (GST_VIDEO_OVERLAY (sink));
+ g_mutex_lock (&sink->render_lock);
- if (sink->visible) {
- render_last_buffer (sink);
- } else {
- GST_LOG ("skip rendering");
+ if (!sink->window) {
+ /* if we were not provided a window, create one ourselves */
+ sink->window =
+ gst_wl_window_new_toplevel (sink->display, &sink->video_info);
}
+ }
- if (buffer != to_render)
- gst_buffer_unref (to_render);
-
+ /* drop buffers until we get a frame callback */
+ if (g_atomic_int_get (&sink->redraw_pending) == TRUE
+ && !gst_wayland_sink_is_gapless (sink))
goto done;
- }
-#else /* open source */
+ /* 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);
"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)) {
+ if (gst_is_wl_shm_memory (mem)) { /* is wayland memory */
FUNCTION;
wbuf = gst_wl_shm_memory_construct_wl_buffer (mem, sink->display,
&sink->video_info);
ret = GST_FLOW_ERROR;
goto done;
}
-#endif
no_buffer:
{
GST_WARNING_OBJECT (sink, "could not create buffer");
ret = GST_FLOW_ERROR;
goto done;
}
+#endif
done:
{
g_mutex_unlock (&sink->render_lock);