mirror of
https://gitlab.freedesktop.org/gstreamer/gstreamer.git
synced 2025-01-18 13:25:56 +00:00
waylandsink: Implement expose() and handle resizing properly in non-PLAYING states
This commit is contained in:
parent
086ac4ee81
commit
66f8c1389b
2 changed files with 62 additions and 34 deletions
|
@ -202,6 +202,8 @@ gst_wayland_sink_finalize (GObject * object)
|
||||||
|
|
||||||
GST_DEBUG_OBJECT (sink, "Finalizing the sink..");
|
GST_DEBUG_OBJECT (sink, "Finalizing the sink..");
|
||||||
|
|
||||||
|
if (sink->last_buffer)
|
||||||
|
gst_buffer_unref (sink->last_buffer);
|
||||||
if (sink->display) {
|
if (sink->display) {
|
||||||
/* see comment about this call in gst_wayland_sink_change_state() */
|
/* see comment about this call in gst_wayland_sink_change_state() */
|
||||||
gst_wayland_compositor_release_all_buffers (GST_WAYLAND_BUFFER_POOL
|
gst_wayland_compositor_release_all_buffers (GST_WAYLAND_BUFFER_POOL
|
||||||
|
@ -258,6 +260,7 @@ gst_wayland_sink_change_state (GstElement * element, GstStateChange transition)
|
||||||
*/
|
*/
|
||||||
gst_wayland_compositor_release_all_buffers (GST_WAYLAND_BUFFER_POOL
|
gst_wayland_compositor_release_all_buffers (GST_WAYLAND_BUFFER_POOL
|
||||||
(sink->pool));
|
(sink->pool));
|
||||||
|
gst_buffer_replace (&sink->last_buffer, NULL);
|
||||||
g_clear_object (&sink->window);
|
g_clear_object (&sink->window);
|
||||||
g_clear_object (&sink->display);
|
g_clear_object (&sink->display);
|
||||||
g_clear_object (&sink->pool);
|
g_clear_object (&sink->pool);
|
||||||
|
@ -495,16 +498,52 @@ static const struct wl_callback_listener frame_callback_listener = {
|
||||||
frame_redraw_callback
|
frame_redraw_callback
|
||||||
};
|
};
|
||||||
|
|
||||||
|
/* must be called with the object lock */
|
||||||
|
static void
|
||||||
|
render_last_buffer (GstWaylandSink * sink)
|
||||||
|
{
|
||||||
|
GstWlMeta *meta;
|
||||||
|
struct wl_surface *surface;
|
||||||
|
struct wl_callback *callback;
|
||||||
|
GstVideoRectangle src, dst, res;
|
||||||
|
|
||||||
|
meta = gst_buffer_get_wl_meta (sink->last_buffer);
|
||||||
|
surface = gst_wl_window_get_wl_surface (sink->window);
|
||||||
|
|
||||||
|
g_atomic_int_set (&sink->redraw_pending, TRUE);
|
||||||
|
callback = wl_surface_frame (surface);
|
||||||
|
wl_callback_add_listener (callback, &frame_callback_listener, sink);
|
||||||
|
|
||||||
|
/* Here we essentially add a reference to the buffer. This represents
|
||||||
|
* the fact that the compositor is using the buffer and it should
|
||||||
|
* not return back to the pool and be reused until the compositor
|
||||||
|
* releases it. The release is handled internally in the pool */
|
||||||
|
gst_wayland_compositor_acquire_buffer (meta->pool, sink->last_buffer);
|
||||||
|
|
||||||
|
src.w = sink->video_width;
|
||||||
|
src.h = sink->video_height;
|
||||||
|
dst.w = sink->window->width;
|
||||||
|
dst.h = sink->window->height;
|
||||||
|
gst_video_sink_center_rect (src, dst, &res, FALSE);
|
||||||
|
|
||||||
|
wl_viewport_set (sink->window->viewport, wl_fixed_from_int (0),
|
||||||
|
wl_fixed_from_int (0), wl_fixed_from_int (src.w),
|
||||||
|
wl_fixed_from_int (src.h), res.w, res.h);
|
||||||
|
|
||||||
|
wl_surface_attach (surface, meta->wbuffer, 0, 0);
|
||||||
|
wl_surface_damage (surface, 0, 0, res.w, res.h);
|
||||||
|
|
||||||
|
wl_surface_commit (surface);
|
||||||
|
wl_display_flush (sink->display->display);
|
||||||
|
}
|
||||||
|
|
||||||
static GstFlowReturn
|
static GstFlowReturn
|
||||||
gst_wayland_sink_render (GstBaseSink * bsink, GstBuffer * buffer)
|
gst_wayland_sink_render (GstBaseSink * bsink, GstBuffer * buffer)
|
||||||
{
|
{
|
||||||
GstWaylandSink *sink = GST_WAYLAND_SINK (bsink);
|
GstWaylandSink *sink = GST_WAYLAND_SINK (bsink);
|
||||||
GstVideoRectangle src, dst, res;
|
|
||||||
GstBuffer *to_render;
|
GstBuffer *to_render;
|
||||||
GstWlMeta *meta;
|
GstWlMeta *meta;
|
||||||
GstFlowReturn ret = GST_FLOW_OK;
|
GstFlowReturn ret = GST_FLOW_OK;
|
||||||
struct wl_surface *surface;
|
|
||||||
struct wl_callback *callback;
|
|
||||||
|
|
||||||
GST_OBJECT_LOCK (sink);
|
GST_OBJECT_LOCK (sink);
|
||||||
|
|
||||||
|
@ -540,38 +579,10 @@ gst_wayland_sink_render (GstBaseSink * bsink, GstBuffer * buffer)
|
||||||
gst_buffer_map (buffer, &src, GST_MAP_READ);
|
gst_buffer_map (buffer, &src, GST_MAP_READ);
|
||||||
gst_buffer_fill (to_render, 0, src.data, src.size);
|
gst_buffer_fill (to_render, 0, src.data, src.size);
|
||||||
gst_buffer_unmap (buffer, &src);
|
gst_buffer_unmap (buffer, &src);
|
||||||
|
|
||||||
meta = gst_buffer_get_wl_meta (to_render);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
src.w = sink->video_width;
|
gst_buffer_replace (&sink->last_buffer, to_render);
|
||||||
src.h = sink->video_height;
|
render_last_buffer (sink);
|
||||||
dst.w = sink->window->width;
|
|
||||||
dst.h = sink->window->height;
|
|
||||||
|
|
||||||
gst_video_sink_center_rect (src, dst, &res, FALSE);
|
|
||||||
|
|
||||||
surface = gst_wl_window_get_wl_surface (sink->window);
|
|
||||||
|
|
||||||
/* Here we essentially add a reference to the buffer. This represents
|
|
||||||
* the fact that the compositor is using the buffer and it should
|
|
||||||
* not return back to the pool and be reused until the compositor
|
|
||||||
* releases it. The release is handled internally in the pool */
|
|
||||||
gst_wayland_compositor_acquire_buffer (meta->pool, to_render);
|
|
||||||
|
|
||||||
g_atomic_int_set (&sink->redraw_pending, TRUE);
|
|
||||||
|
|
||||||
wl_surface_attach (surface, meta->wbuffer, 0, 0);
|
|
||||||
wl_surface_damage (surface, 0, 0, res.w, res.h);
|
|
||||||
|
|
||||||
wl_viewport_set (sink->window->viewport, wl_fixed_from_int (0),
|
|
||||||
wl_fixed_from_int (0), wl_fixed_from_int (src.w),
|
|
||||||
wl_fixed_from_int (src.h), res.w, res.h);
|
|
||||||
|
|
||||||
callback = wl_surface_frame (surface);
|
|
||||||
wl_callback_add_listener (callback, &frame_callback_listener, sink);
|
|
||||||
wl_surface_commit (surface);
|
|
||||||
wl_display_flush (sink->display->display);
|
|
||||||
|
|
||||||
/* notify _resume_rendering() in case it's waiting */
|
/* notify _resume_rendering() in case it's waiting */
|
||||||
g_cond_broadcast (&sink->render_cond);
|
g_cond_broadcast (&sink->render_cond);
|
||||||
|
@ -664,7 +675,17 @@ static void
|
||||||
gst_wayland_sink_expose (GstVideoOverlay * overlay)
|
gst_wayland_sink_expose (GstVideoOverlay * overlay)
|
||||||
{
|
{
|
||||||
GstWaylandSink *sink = GST_WAYLAND_SINK (overlay);
|
GstWaylandSink *sink = GST_WAYLAND_SINK (overlay);
|
||||||
|
|
||||||
g_return_if_fail (sink != NULL);
|
g_return_if_fail (sink != NULL);
|
||||||
|
|
||||||
|
GST_DEBUG_OBJECT (sink, "expose");
|
||||||
|
|
||||||
|
GST_OBJECT_LOCK (sink);
|
||||||
|
if (sink->last_buffer && g_atomic_int_get (&sink->redraw_pending) == FALSE) {
|
||||||
|
GST_DEBUG_OBJECT (sink, "redrawing last buffer");
|
||||||
|
render_last_buffer (sink);
|
||||||
|
}
|
||||||
|
GST_OBJECT_UNLOCK (sink);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void
|
static void
|
||||||
|
@ -714,7 +735,13 @@ gst_wayland_sink_resume_rendering (GstWaylandVideo * video)
|
||||||
|
|
||||||
GST_OBJECT_LOCK (sink);
|
GST_OBJECT_LOCK (sink);
|
||||||
sink->drawing_frozen = FALSE;
|
sink->drawing_frozen = FALSE;
|
||||||
|
|
||||||
|
if (GST_STATE (sink) == GST_STATE_PLAYING)
|
||||||
g_cond_wait (&sink->render_cond, GST_OBJECT_GET_LOCK (sink));
|
g_cond_wait (&sink->render_cond, GST_OBJECT_GET_LOCK (sink));
|
||||||
|
else if (sink->window && sink->last_buffer &&
|
||||||
|
g_atomic_int_get (&sink->redraw_pending) == FALSE)
|
||||||
|
render_last_buffer (sink);
|
||||||
|
|
||||||
GST_OBJECT_UNLOCK (sink);
|
GST_OBJECT_UNLOCK (sink);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -64,6 +64,7 @@ struct _GstWaylandSink
|
||||||
gboolean redraw_pending;
|
gboolean redraw_pending;
|
||||||
gboolean drawing_frozen;
|
gboolean drawing_frozen;
|
||||||
GCond render_cond;
|
GCond render_cond;
|
||||||
|
GstBuffer *last_buffer;
|
||||||
};
|
};
|
||||||
|
|
||||||
struct _GstWaylandSinkClass
|
struct _GstWaylandSinkClass
|
||||||
|
|
Loading…
Reference in a new issue