mirror of
https://gitlab.freedesktop.org/gstreamer/gstreamer.git
synced 2025-06-05 06:58:56 +00:00
waylandsink: Rework dmabuf support
Simplify and fix some of the show_frame logic. https://bugzilla.gnome.org/show_bug.cgi?id=711155
This commit is contained in:
parent
2ad337e440
commit
5d01d3bbb8
5 changed files with 88 additions and 79 deletions
|
@ -472,7 +472,6 @@ static gboolean
|
||||||
gst_wayland_sink_set_caps (GstBaseSink * bsink, GstCaps * caps)
|
gst_wayland_sink_set_caps (GstBaseSink * bsink, GstCaps * caps)
|
||||||
{
|
{
|
||||||
GstWaylandSink *sink;
|
GstWaylandSink *sink;
|
||||||
GstBufferPool *newpool;
|
|
||||||
gboolean use_dmabuf;
|
gboolean use_dmabuf;
|
||||||
GstVideoFormat format;
|
GstVideoFormat format;
|
||||||
|
|
||||||
|
@ -487,35 +486,20 @@ gst_wayland_sink_set_caps (GstBaseSink * bsink, GstCaps * caps)
|
||||||
format = GST_VIDEO_INFO_FORMAT (&sink->video_info);
|
format = GST_VIDEO_INFO_FORMAT (&sink->video_info);
|
||||||
sink->video_info_changed = TRUE;
|
sink->video_info_changed = TRUE;
|
||||||
|
|
||||||
|
/* create a new pool for the new caps */
|
||||||
|
if (sink->pool)
|
||||||
|
gst_object_unref (sink->pool);
|
||||||
|
sink->pool = gst_wayland_create_pool (sink, caps);
|
||||||
|
|
||||||
use_dmabuf = gst_caps_features_contains (gst_caps_get_features (caps, 0),
|
use_dmabuf = gst_caps_features_contains (gst_caps_get_features (caps, 0),
|
||||||
GST_CAPS_FEATURE_MEMORY_DMABUF);
|
GST_CAPS_FEATURE_MEMORY_DMABUF);
|
||||||
|
|
||||||
if (!use_dmabuf) {
|
/* validate the format base on the memory type. */
|
||||||
/* shm - verify format support */
|
if (use_dmabuf) {
|
||||||
enum wl_shm_format format_shm = gst_video_format_to_wl_shm_format (format);
|
if (!gst_wl_display_check_format_for_dmabuf (sink->display, format))
|
||||||
if ((gint) format_shm == -1)
|
|
||||||
goto invalid_format;
|
|
||||||
|
|
||||||
if (!is_shm_format_supported (format_shm, sink->display))
|
|
||||||
goto unsupported_format;
|
goto unsupported_format;
|
||||||
|
} else if (!gst_wl_display_check_format_for_shm (sink->display, format)) {
|
||||||
/* create a new pool for the new configuration */
|
goto unsupported_format;
|
||||||
newpool = gst_wayland_create_pool (sink, caps);
|
|
||||||
if (!newpool)
|
|
||||||
goto pool_failed;
|
|
||||||
|
|
||||||
gst_object_replace ((GstObject **) & sink->pool, (GstObject *) newpool);
|
|
||||||
gst_object_unref (newpool);
|
|
||||||
} else {
|
|
||||||
/* dmabuf - verify format support */
|
|
||||||
gint format_dmabuf = gst_video_format_to_wl_dmabuf_format (format);
|
|
||||||
if (format_dmabuf == -1)
|
|
||||||
goto invalid_format;
|
|
||||||
|
|
||||||
if (!is_dmabuf_format_supported (format_dmabuf, sink->display))
|
|
||||||
goto unsupported_format;
|
|
||||||
|
|
||||||
/* No pool for dmabuf, this is under upstream element responsability */
|
|
||||||
}
|
}
|
||||||
|
|
||||||
sink->use_dmabuf = use_dmabuf;
|
sink->use_dmabuf = use_dmabuf;
|
||||||
|
@ -534,11 +518,6 @@ unsupported_format:
|
||||||
gst_video_format_to_string (format));
|
gst_video_format_to_string (format));
|
||||||
return FALSE;
|
return FALSE;
|
||||||
}
|
}
|
||||||
pool_failed:
|
|
||||||
{
|
|
||||||
GST_ERROR_OBJECT (sink, "Failed to create new pool");
|
|
||||||
return FALSE;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static gboolean
|
static gboolean
|
||||||
|
@ -612,6 +591,11 @@ gst_wayland_sink_show_frame (GstVideoSink * vsink, GstBuffer * buffer)
|
||||||
GstWaylandSink *sink = GST_WAYLAND_SINK (vsink);
|
GstWaylandSink *sink = GST_WAYLAND_SINK (vsink);
|
||||||
GstBuffer *to_render;
|
GstBuffer *to_render;
|
||||||
GstWlBuffer *wlbuffer;
|
GstWlBuffer *wlbuffer;
|
||||||
|
GstVideoMeta *vmeta;
|
||||||
|
GstVideoFormat format;
|
||||||
|
GstMemory *mem;
|
||||||
|
struct wl_buffer *wbuf = NULL;
|
||||||
|
|
||||||
GstFlowReturn ret = GST_FLOW_OK;
|
GstFlowReturn ret = GST_FLOW_OK;
|
||||||
|
|
||||||
g_mutex_lock (&sink->render_lock);
|
g_mutex_lock (&sink->render_lock);
|
||||||
|
@ -646,45 +630,42 @@ gst_wayland_sink_show_frame (GstVideoSink * vsink, GstBuffer * buffer)
|
||||||
GST_LOG_OBJECT (sink, "buffer %p has a wl_buffer from our display, "
|
GST_LOG_OBJECT (sink, "buffer %p has a wl_buffer from our display, "
|
||||||
"writing directly", buffer);
|
"writing directly", buffer);
|
||||||
to_render = buffer;
|
to_render = buffer;
|
||||||
} else {
|
goto render;
|
||||||
GstVideoMeta *vmeta;
|
}
|
||||||
GstMemory *mem;
|
|
||||||
struct wl_buffer *wbuf = NULL;
|
|
||||||
|
|
||||||
/* update video info from video meta */
|
/* update video info from video meta */
|
||||||
vmeta = gst_buffer_get_video_meta (buffer);
|
vmeta = gst_buffer_get_video_meta (buffer);
|
||||||
if (vmeta) {
|
if (vmeta) {
|
||||||
gint i;
|
gint i;
|
||||||
|
|
||||||
for (i = 0; i < vmeta->n_planes; i++) {
|
for (i = 0; i < vmeta->n_planes; i++) {
|
||||||
sink->video_info.offset[i] = vmeta->offset[i];
|
sink->video_info.offset[i] = vmeta->offset[i];
|
||||||
sink->video_info.stride[i] = vmeta->stride[i];
|
sink->video_info.stride[i] = vmeta->stride[i];
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
GST_LOG_OBJECT (sink, "buffer %p does not have a wl_buffer from our "
|
GST_LOG_OBJECT (sink, "buffer %p does not have a wl_buffer from our "
|
||||||
"display, creating it", buffer);
|
"display, creating it", buffer);
|
||||||
|
|
||||||
mem = gst_buffer_peek_memory (buffer, 0);
|
mem = gst_buffer_peek_memory (buffer, 0);
|
||||||
|
|
||||||
|
format = GST_VIDEO_INFO_FORMAT (&sink->video_info);
|
||||||
|
if (gst_wl_display_check_format_for_dmabuf (sink->display, format)) {
|
||||||
|
guint i, nb_dmabuf = 0;
|
||||||
|
|
||||||
|
for (i = 0; i < gst_buffer_n_memory (buffer); i++)
|
||||||
|
if (gst_is_dmabuf_memory (gst_buffer_peek_memory (buffer, i)))
|
||||||
|
nb_dmabuf++;
|
||||||
|
|
||||||
|
if (nb_dmabuf && (nb_dmabuf == gst_buffer_n_memory (buffer)))
|
||||||
|
wbuf = gst_wl_linux_dmabuf_construct_wl_buffer (buffer, sink->display,
|
||||||
|
&sink->video_info);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!wbuf && gst_wl_display_check_format_for_shm (sink->display, format)) {
|
||||||
if (gst_is_fd_memory (mem)) {
|
if (gst_is_fd_memory (mem)) {
|
||||||
wbuf = gst_wl_shm_memory_construct_wl_buffer (mem, sink->display,
|
wbuf = gst_wl_shm_memory_construct_wl_buffer (mem, sink->display,
|
||||||
&sink->video_info);
|
&sink->video_info);
|
||||||
} else if (sink->display->dmabuf) {
|
|
||||||
guint i, nb_dmabuf = 0;
|
|
||||||
|
|
||||||
for (i = 0; i < gst_buffer_n_memory (buffer); i++)
|
|
||||||
if (gst_is_dmabuf_memory (gst_buffer_peek_memory (buffer, i)))
|
|
||||||
nb_dmabuf++;
|
|
||||||
|
|
||||||
if (nb_dmabuf && (nb_dmabuf == gst_buffer_n_memory (buffer)))
|
|
||||||
wbuf = gst_wl_linux_dmabuf_construct_wl_buffer (buffer, sink->display,
|
|
||||||
&sink->video_info);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (wbuf) {
|
|
||||||
gst_buffer_add_wl_buffer (buffer, wbuf, sink->display);
|
|
||||||
to_render = buffer;
|
|
||||||
} else {
|
} else {
|
||||||
GstVideoFrame src, dst;
|
GstVideoFrame src, dst;
|
||||||
GstVideoInfo src_info = sink->video_info;
|
GstVideoInfo src_info = sink->video_info;
|
||||||
|
@ -717,21 +698,18 @@ gst_wayland_sink_show_frame (GstVideoSink * vsink, GstBuffer * buffer)
|
||||||
if (ret != GST_FLOW_OK)
|
if (ret != GST_FLOW_OK)
|
||||||
goto no_buffer;
|
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 (to_render);
|
wlbuffer = gst_buffer_get_wl_buffer (to_render);
|
||||||
|
|
||||||
|
/* attach a wl_buffer if there isn't one yet */
|
||||||
if (G_UNLIKELY (!wlbuffer)) {
|
if (G_UNLIKELY (!wlbuffer)) {
|
||||||
mem = gst_buffer_peek_memory (to_render, 0);
|
mem = gst_buffer_peek_memory (to_render, 0);
|
||||||
wbuf = gst_wl_shm_memory_construct_wl_buffer (mem, sink->display,
|
wbuf = gst_wl_shm_memory_construct_wl_buffer (mem, sink->display,
|
||||||
&sink->video_info);
|
&sink->video_info);
|
||||||
|
|
||||||
if (G_UNLIKELY (!wbuf))
|
if (G_UNLIKELY (!wbuf))
|
||||||
goto no_wl_buffer_shm;
|
goto no_wl_buffer_shm;
|
||||||
|
|
||||||
gst_buffer_add_wl_buffer (to_render, wbuf, sink->display);
|
gst_buffer_add_wl_buffer (to_render, wbuf, sink->display);
|
||||||
} else {
|
|
||||||
/* we cannot get a wl_buffer and if we do not have any pool to create
|
|
||||||
* one by ourself */
|
|
||||||
goto no_wl_buffer;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!gst_video_frame_map (&dst, &sink->video_info, to_render,
|
if (!gst_video_frame_map (&dst, &sink->video_info, to_render,
|
||||||
|
@ -747,9 +725,18 @@ gst_wayland_sink_show_frame (GstVideoSink * vsink, GstBuffer * buffer)
|
||||||
|
|
||||||
gst_video_frame_unmap (&src);
|
gst_video_frame_unmap (&src);
|
||||||
gst_video_frame_unmap (&dst);
|
gst_video_frame_unmap (&dst);
|
||||||
|
|
||||||
|
goto render;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (!wbuf)
|
||||||
|
goto no_wl_buffer;
|
||||||
|
|
||||||
|
gst_buffer_add_wl_buffer (buffer, wbuf, sink->display);
|
||||||
|
to_render = buffer;
|
||||||
|
|
||||||
|
render:
|
||||||
/* drop double rendering */
|
/* drop double rendering */
|
||||||
if (G_UNLIKELY (to_render == sink->last_buffer)) {
|
if (G_UNLIKELY (to_render == sink->last_buffer)) {
|
||||||
GST_LOG_OBJECT (sink, "Buffer already being rendered");
|
GST_LOG_OBJECT (sink, "Buffer already being rendered");
|
||||||
|
|
|
@ -168,14 +168,20 @@ static const struct zwp_linux_dmabuf_v1_listener dmabuf_listener = {
|
||||||
};
|
};
|
||||||
|
|
||||||
gboolean
|
gboolean
|
||||||
is_shm_format_supported (enum wl_shm_format format_shm, GstWlDisplay * display)
|
gst_wl_display_check_format_for_shm (GstWlDisplay * display,
|
||||||
|
GstVideoFormat format)
|
||||||
{
|
{
|
||||||
|
enum wl_shm_format shm_fmt;
|
||||||
GArray *formats;
|
GArray *formats;
|
||||||
guint i;
|
guint i;
|
||||||
|
|
||||||
|
shm_fmt = gst_video_format_to_wl_shm_format (format);
|
||||||
|
if (shm_fmt < 0)
|
||||||
|
return FALSE;
|
||||||
|
|
||||||
formats = display->shm_formats;
|
formats = display->shm_formats;
|
||||||
for (i = 0; i < formats->len; i++) {
|
for (i = 0; i < formats->len; i++) {
|
||||||
if (g_array_index (formats, uint32_t, i) == format_shm)
|
if (g_array_index (formats, uint32_t, i) == shm_fmt)
|
||||||
return TRUE;
|
return TRUE;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -183,14 +189,22 @@ is_shm_format_supported (enum wl_shm_format format_shm, GstWlDisplay * display)
|
||||||
}
|
}
|
||||||
|
|
||||||
gboolean
|
gboolean
|
||||||
is_dmabuf_format_supported (guint format_dmabuf, GstWlDisplay * display)
|
gst_wl_display_check_format_for_dmabuf (GstWlDisplay * display,
|
||||||
|
GstVideoFormat format)
|
||||||
{
|
{
|
||||||
GArray *formats;
|
GArray *formats;
|
||||||
guint i;
|
guint i, dmabuf_fmt;
|
||||||
|
|
||||||
|
if (!display->dmabuf)
|
||||||
|
return FALSE;
|
||||||
|
|
||||||
|
dmabuf_fmt = gst_video_format_to_wl_dmabuf_format (format);
|
||||||
|
if (dmabuf_fmt < 0)
|
||||||
|
return FALSE;
|
||||||
|
|
||||||
formats = display->dmabuf_formats;
|
formats = display->dmabuf_formats;
|
||||||
for (i = 0; i < formats->len; i++) {
|
for (i = 0; i < formats->len; i++) {
|
||||||
if (g_array_index (formats, uint32_t, i) == format_dmabuf)
|
if (g_array_index (formats, uint32_t, i) == dmabuf_fmt)
|
||||||
return TRUE;
|
return TRUE;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -22,6 +22,7 @@
|
||||||
#define __GST_WL_DISPLAY_H__
|
#define __GST_WL_DISPLAY_H__
|
||||||
|
|
||||||
#include <gst/gst.h>
|
#include <gst/gst.h>
|
||||||
|
#include <gst/video/video.h>
|
||||||
#include <wayland-client.h>
|
#include <wayland-client.h>
|
||||||
#include "viewporter-client-protocol.h"
|
#include "viewporter-client-protocol.h"
|
||||||
#include "linux-dmabuf-unstable-v1-client-protocol.h"
|
#include "linux-dmabuf-unstable-v1-client-protocol.h"
|
||||||
|
@ -82,10 +83,10 @@ GstWlDisplay *gst_wl_display_new_existing (struct wl_display * display,
|
||||||
void gst_wl_display_register_buffer (GstWlDisplay * self, gpointer buf);
|
void gst_wl_display_register_buffer (GstWlDisplay * self, gpointer buf);
|
||||||
void gst_wl_display_unregister_buffer (GstWlDisplay * self, gpointer buf);
|
void gst_wl_display_unregister_buffer (GstWlDisplay * self, gpointer buf);
|
||||||
|
|
||||||
gboolean is_shm_format_supported (enum wl_shm_format format_shm,
|
gboolean gst_wl_display_check_format_for_shm (GstWlDisplay * display,
|
||||||
GstWlDisplay * display);
|
GstVideoFormat format);
|
||||||
gboolean is_dmabuf_format_supported (guint format_dmabuf,
|
gboolean gst_wl_display_check_format_for_dmabuf (GstWlDisplay * display,
|
||||||
GstWlDisplay * display);
|
GstVideoFormat format);
|
||||||
|
|
||||||
G_END_DECLS
|
G_END_DECLS
|
||||||
|
|
||||||
|
|
|
@ -80,9 +80,11 @@ gst_wl_linux_dmabuf_construct_wl_buffer (GstBuffer * buf,
|
||||||
gint64 timeout;
|
gint64 timeout;
|
||||||
ConstructBufferData data;
|
ConstructBufferData data;
|
||||||
|
|
||||||
|
g_return_val_if_fail (gst_wl_display_check_format_for_dmabuf (display,
|
||||||
|
GST_VIDEO_INFO_FORMAT (info)), NULL);
|
||||||
|
|
||||||
mem = gst_buffer_peek_memory (buf, 0);
|
mem = gst_buffer_peek_memory (buf, 0);
|
||||||
format = gst_video_format_to_wl_dmabuf_format (GST_VIDEO_INFO_FORMAT (info));
|
format = gst_video_format_to_wl_dmabuf_format (GST_VIDEO_INFO_FORMAT (info));
|
||||||
g_return_val_if_fail (is_dmabuf_format_supported (format, display), NULL);
|
|
||||||
|
|
||||||
g_cond_init (&data.cond);
|
g_cond_init (&data.cond);
|
||||||
g_mutex_init (&data.lock);
|
g_mutex_init (&data.lock);
|
||||||
|
@ -93,6 +95,10 @@ gst_wl_linux_dmabuf_construct_wl_buffer (GstBuffer * buf,
|
||||||
nplanes = GST_VIDEO_INFO_N_PLANES (info);
|
nplanes = GST_VIDEO_INFO_N_PLANES (info);
|
||||||
nmem = gst_buffer_n_memory (buf);
|
nmem = gst_buffer_n_memory (buf);
|
||||||
|
|
||||||
|
GST_DEBUG_OBJECT (display, "Creating wl_buffer from DMABuf of size %"
|
||||||
|
G_GSSIZE_FORMAT " (%d x %d), format %s", info->size, width, height,
|
||||||
|
gst_wl_dmabuf_format_to_string (format));
|
||||||
|
|
||||||
/* Creation and configuration of planes */
|
/* Creation and configuration of planes */
|
||||||
params = zwp_linux_dmabuf_v1_create_params (display->dmabuf);
|
params = zwp_linux_dmabuf_v1_create_params (display->dmabuf);
|
||||||
|
|
||||||
|
|
|
@ -146,9 +146,10 @@ gst_wl_shm_memory_construct_wl_buffer (GstMemory * mem, GstWlDisplay * display,
|
||||||
|
|
||||||
g_return_val_if_fail (gst_is_fd_memory (mem), NULL);
|
g_return_val_if_fail (gst_is_fd_memory (mem), NULL);
|
||||||
g_return_val_if_fail (size <= memsize, NULL);
|
g_return_val_if_fail (size <= memsize, NULL);
|
||||||
g_return_val_if_fail (is_shm_format_supported (format, display), NULL);
|
g_return_val_if_fail (gst_wl_display_check_format_for_shm (display,
|
||||||
|
GST_VIDEO_INFO_FORMAT (info)), NULL);
|
||||||
|
|
||||||
GST_DEBUG_OBJECT (mem->allocator, "Creating wl_buffer of size %"
|
GST_DEBUG_OBJECT (display, "Creating wl_buffer from SHM of size %"
|
||||||
G_GSSIZE_FORMAT " (%d x %d, stride %d), format %s", size, width, height,
|
G_GSSIZE_FORMAT " (%d x %d, stride %d), format %s", size, width, height,
|
||||||
stride, gst_wl_shm_format_to_string (format));
|
stride, gst_wl_shm_format_to_string (format));
|
||||||
|
|
||||||
|
|
Loading…
Reference in a new issue