mirror of
https://gitlab.freedesktop.org/gstreamer/gstreamer.git
synced 2024-12-24 09:10:36 +00:00
waylandsink: support linux dmabuf protocol
Support the wayland zwp_linux_dmabuf_unstable_v1 protocol. SHM formats and DMABuf formats are exposed differently in caps: the DMABuf formats are flagged with GST_CAPS_FEATURE_MEMORY_DMABUF. No buffer pool is proposed for DMABuf buffers, it is the upstream element responsibility to provide with such buffers. https://bugzilla.gnome.org/show_bug.cgi?id=711155
This commit is contained in:
parent
3272f2002f
commit
2ad337e440
10 changed files with 430 additions and 56 deletions
|
@ -1,6 +1,10 @@
|
|||
plugin_LTLIBRARIES = libgstwaylandsink.la
|
||||
|
||||
BUILT_SOURCES = viewporter-protocol.c viewporter-client-protocol.h
|
||||
BUILT_SOURCES = \
|
||||
viewporter-protocol.c \
|
||||
viewporter-client-protocol.h \
|
||||
linux-dmabuf-unstable-v1-protocol.c \
|
||||
linux-dmabuf-unstable-v1-client-protocol.h
|
||||
|
||||
libgstwaylandsink_la_SOURCES = \
|
||||
gstwaylandsink.c \
|
||||
|
@ -8,9 +12,12 @@ libgstwaylandsink_la_SOURCES = \
|
|||
wlbuffer.c \
|
||||
wldisplay.c \
|
||||
wlwindow.c \
|
||||
wlvideoformat.c
|
||||
wlvideoformat.c \
|
||||
wllinuxdmabuf.c
|
||||
|
||||
nodist_libgstwaylandsink_la_SOURCES = viewporter-protocol.c
|
||||
nodist_libgstwaylandsink_la_SOURCES = \
|
||||
viewporter-protocol.c \
|
||||
linux-dmabuf-unstable-v1-protocol.c
|
||||
|
||||
libgstwaylandsink_la_CFLAGS = $(GST_CFLAGS) $(GST_PLUGINS_BASE_CFLAGS) \
|
||||
$(WAYLAND_CFLAGS) $(GST_PLUGINS_BAD_CFLAGS)
|
||||
|
@ -29,7 +36,8 @@ noinst_HEADERS = \
|
|||
wlbuffer.h \
|
||||
wldisplay.h \
|
||||
wlwindow.h \
|
||||
wlvideoformat.h
|
||||
wlvideoformat.h \
|
||||
wllinuxdmabuf.h
|
||||
|
||||
CLEANFILES = $(BUILT_SOURCES)
|
||||
|
||||
|
|
|
@ -45,6 +45,7 @@
|
|||
#include "wlvideoformat.h"
|
||||
#include "wlbuffer.h"
|
||||
#include "wlshmallocator.h"
|
||||
#include "wllinuxdmabuf.h"
|
||||
|
||||
#include <gst/wayland/wayland.h>
|
||||
#include <gst/video/videooverlay.h>
|
||||
|
@ -66,13 +67,17 @@ enum
|
|||
GST_DEBUG_CATEGORY (gstwayland_debug);
|
||||
#define GST_CAT_DEFAULT gstwayland_debug
|
||||
|
||||
#define WL_VIDEO_FORMATS \
|
||||
"{ BGRx, BGRA, RGBx, xBGR, xRGB, RGBA, ABGR, ARGB, RGB, BGR, " \
|
||||
"RGB16, BGR16, YUY2, YVYU, UYVY, AYUV, NV12, NV21, NV16, " \
|
||||
"YUV9, YVU9, Y41B, I420, YV12, Y42B, v308 }"
|
||||
|
||||
static GstStaticPadTemplate sink_template = GST_STATIC_PAD_TEMPLATE ("sink",
|
||||
GST_PAD_SINK,
|
||||
GST_PAD_ALWAYS,
|
||||
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, "
|
||||
"YUV9, YVU9, Y41B, I420, YV12, Y42B, v308 }"))
|
||||
GST_STATIC_CAPS (GST_VIDEO_CAPS_MAKE (WL_VIDEO_FORMATS) ";"
|
||||
GST_VIDEO_CAPS_MAKE_WITH_FEATURES (GST_CAPS_FEATURE_MEMORY_DMABUF,
|
||||
WL_VIDEO_FORMATS))
|
||||
);
|
||||
|
||||
static void gst_wayland_sink_get_property (GObject * object,
|
||||
|
@ -386,29 +391,43 @@ gst_wayland_sink_get_caps (GstBaseSink * bsink, GstCaps * filter)
|
|||
sink = GST_WAYLAND_SINK (bsink);
|
||||
|
||||
caps = gst_pad_get_pad_template_caps (GST_VIDEO_SINK_PAD (sink));
|
||||
caps = gst_caps_make_writable (caps);
|
||||
|
||||
g_mutex_lock (&sink->display_lock);
|
||||
|
||||
if (sink->display) {
|
||||
GValue list = G_VALUE_INIT;
|
||||
GValue shm_list = G_VALUE_INIT, dmabuf_list = G_VALUE_INIT;
|
||||
GValue value = G_VALUE_INIT;
|
||||
GArray *formats;
|
||||
gint i;
|
||||
enum wl_shm_format fmt;
|
||||
guint fmt;
|
||||
|
||||
g_value_init (&list, GST_TYPE_LIST);
|
||||
g_value_init (&shm_list, GST_TYPE_LIST);
|
||||
g_value_init (&dmabuf_list, GST_TYPE_LIST);
|
||||
|
||||
/* Add corresponding shm formats */
|
||||
formats = sink->display->shm_formats;
|
||||
for (i = 0; i < formats->len; i++) {
|
||||
g_value_init (&value, G_TYPE_STRING);
|
||||
fmt = g_array_index (formats, uint32_t, i);
|
||||
g_value_set_static_string (&value, gst_wl_shm_format_to_string (fmt));
|
||||
gst_value_list_append_and_take_value (&list, &value);
|
||||
gst_value_list_append_and_take_value (&shm_list, &value);
|
||||
}
|
||||
|
||||
caps = gst_caps_make_writable (caps);
|
||||
gst_structure_take_value (gst_caps_get_structure (caps, 0), "format",
|
||||
&list);
|
||||
&shm_list);
|
||||
|
||||
/* Add corresponding dmabuf formats */
|
||||
formats = sink->display->dmabuf_formats;
|
||||
for (i = 0; i < formats->len; i++) {
|
||||
g_value_init (&value, G_TYPE_STRING);
|
||||
fmt = g_array_index (formats, uint32_t, i);
|
||||
g_value_set_static_string (&value, gst_wl_dmabuf_format_to_string (fmt));
|
||||
gst_value_list_append_and_take_value (&dmabuf_list, &value);
|
||||
}
|
||||
|
||||
gst_structure_take_value (gst_caps_get_structure (caps, 1), "format",
|
||||
&dmabuf_list);
|
||||
|
||||
GST_DEBUG_OBJECT (sink, "display caps: %" GST_PTR_FORMAT, caps);
|
||||
}
|
||||
|
@ -454,45 +473,52 @@ gst_wayland_sink_set_caps (GstBaseSink * bsink, GstCaps * caps)
|
|||
{
|
||||
GstWaylandSink *sink;
|
||||
GstBufferPool *newpool;
|
||||
GstVideoInfo info;
|
||||
enum wl_shm_format format;
|
||||
GArray *formats;
|
||||
gint i;
|
||||
gboolean use_dmabuf;
|
||||
GstVideoFormat format;
|
||||
|
||||
sink = GST_WAYLAND_SINK (bsink);
|
||||
|
||||
GST_DEBUG_OBJECT (sink, "set caps %" GST_PTR_FORMAT, caps);
|
||||
|
||||
/* extract info from caps */
|
||||
if (!gst_video_info_from_caps (&info, caps))
|
||||
if (!gst_video_info_from_caps (&sink->video_info, caps))
|
||||
goto invalid_format;
|
||||
|
||||
format = gst_video_format_to_wl_shm_format (GST_VIDEO_INFO_FORMAT (&info));
|
||||
if ((gint) format == -1)
|
||||
goto invalid_format;
|
||||
|
||||
/* verify we support the requested format */
|
||||
formats = sink->display->shm_formats;
|
||||
for (i = 0; i < formats->len; i++) {
|
||||
if (g_array_index (formats, uint32_t, i) == format)
|
||||
break;
|
||||
}
|
||||
|
||||
if (i >= formats->len)
|
||||
goto unsupported_format;
|
||||
|
||||
/* store the video info */
|
||||
sink->video_info = info;
|
||||
format = GST_VIDEO_INFO_FORMAT (&sink->video_info);
|
||||
sink->video_info_changed = TRUE;
|
||||
|
||||
/* create a new pool for the new configuration */
|
||||
newpool = gst_wayland_create_pool (sink, caps);
|
||||
if (!newpool)
|
||||
goto pool_failed;
|
||||
use_dmabuf = gst_caps_features_contains (gst_caps_get_features (caps, 0),
|
||||
GST_CAPS_FEATURE_MEMORY_DMABUF);
|
||||
|
||||
if (!use_dmabuf) {
|
||||
/* shm - verify format support */
|
||||
enum wl_shm_format format_shm = gst_video_format_to_wl_shm_format (format);
|
||||
if ((gint) format_shm == -1)
|
||||
goto invalid_format;
|
||||
|
||||
gst_object_replace ((GstObject **) & sink->pool, (GstObject *) newpool);
|
||||
gst_object_unref (newpool);
|
||||
if (!is_shm_format_supported (format_shm, sink->display))
|
||||
goto unsupported_format;
|
||||
|
||||
/* create a new pool for the new configuration */
|
||||
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;
|
||||
|
||||
return TRUE;
|
||||
|
||||
|
@ -505,7 +531,7 @@ invalid_format:
|
|||
unsupported_format:
|
||||
{
|
||||
GST_ERROR_OBJECT (sink, "Format %s is not available on the display",
|
||||
gst_wl_shm_format_to_string (format));
|
||||
gst_video_format_to_string (format));
|
||||
return FALSE;
|
||||
}
|
||||
pool_failed:
|
||||
|
@ -639,12 +665,21 @@ gst_wayland_sink_show_frame (GstVideoSink * vsink, GstBuffer * buffer)
|
|||
GST_LOG_OBJECT (sink, "buffer %p does not have a wl_buffer from our "
|
||||
"display, creating it", buffer);
|
||||
|
||||
/* FIXME check all memory when introducing DMA-Buf */
|
||||
mem = gst_buffer_peek_memory (buffer, 0);
|
||||
|
||||
if (gst_is_fd_memory (mem)) {
|
||||
wbuf = gst_wl_shm_memory_construct_wl_buffer (mem, sink->display,
|
||||
&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) {
|
||||
|
@ -655,7 +690,7 @@ gst_wayland_sink_show_frame (GstVideoSink * vsink, GstBuffer * buffer)
|
|||
GstVideoInfo src_info = sink->video_info;
|
||||
|
||||
/* 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
|
||||
* memory, so we have to copy the data to shm memory that we know how
|
||||
* to handle... */
|
||||
|
||||
GST_LOG_OBJECT (sink, "buffer %p cannot have a wl_buffer, "
|
||||
|
@ -690,9 +725,13 @@ gst_wayland_sink_show_frame (GstVideoSink * vsink, GstBuffer * buffer)
|
|||
wbuf = gst_wl_shm_memory_construct_wl_buffer (mem, sink->display,
|
||||
&sink->video_info);
|
||||
if (G_UNLIKELY (!wbuf))
|
||||
goto no_wl_buffer;
|
||||
goto no_wl_buffer_shm;
|
||||
|
||||
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,
|
||||
|
@ -737,12 +776,18 @@ no_buffer:
|
|||
GST_WARNING_OBJECT (sink, "could not create buffer");
|
||||
goto done;
|
||||
}
|
||||
no_wl_buffer:
|
||||
no_wl_buffer_shm:
|
||||
{
|
||||
GST_ERROR_OBJECT (sink, "could not create wl_buffer out of wl_shm memory");
|
||||
ret = GST_FLOW_ERROR;
|
||||
goto done;
|
||||
}
|
||||
no_wl_buffer:
|
||||
{
|
||||
GST_ERROR_OBJECT (sink, "buffer %p cannot have a wl_buffer", buffer);
|
||||
ret = GST_FLOW_ERROR;
|
||||
goto done;
|
||||
}
|
||||
activate_failed:
|
||||
{
|
||||
GST_ERROR_OBJECT (sink, "failed to activate bufferpool.");
|
||||
|
|
|
@ -56,6 +56,7 @@ struct _GstWaylandSink
|
|||
GstWlDisplay *display;
|
||||
GstWlWindow *window;
|
||||
GstBufferPool *pool;
|
||||
gboolean use_dmabuf;
|
||||
|
||||
gboolean video_info_changed;
|
||||
GstVideoInfo video_info;
|
||||
|
|
|
@ -24,6 +24,7 @@
|
|||
|
||||
#include "wldisplay.h"
|
||||
#include "wlbuffer.h"
|
||||
#include "wlvideoformat.h"
|
||||
|
||||
#include <errno.h>
|
||||
|
||||
|
@ -45,6 +46,7 @@ static void
|
|||
gst_wl_display_init (GstWlDisplay * self)
|
||||
{
|
||||
self->shm_formats = g_array_new (FALSE, FALSE, sizeof (uint32_t));
|
||||
self->dmabuf_formats = g_array_new (FALSE, FALSE, sizeof (uint32_t));
|
||||
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);
|
||||
|
@ -71,6 +73,7 @@ gst_wl_display_finalize (GObject * gobject)
|
|||
g_hash_table_remove_all (self->buffers);
|
||||
|
||||
g_array_unref (self->shm_formats);
|
||||
g_array_unref (self->dmabuf_formats);
|
||||
gst_poll_free (self->wl_fd_poll);
|
||||
g_hash_table_unref (self->buffers);
|
||||
g_mutex_clear (&self->buffers_mutex);
|
||||
|
@ -81,6 +84,9 @@ gst_wl_display_finalize (GObject * gobject)
|
|||
if (self->shm)
|
||||
wl_shm_destroy (self->shm);
|
||||
|
||||
if (self->dmabuf)
|
||||
zwp_linux_dmabuf_v1_destroy (self->dmabuf);
|
||||
|
||||
if (self->shell)
|
||||
wl_shell_destroy (self->shell);
|
||||
|
||||
|
@ -147,6 +153,50 @@ static const struct wl_shm_listener shm_listener = {
|
|||
shm_format
|
||||
};
|
||||
|
||||
static void
|
||||
dmabuf_format (void *data, struct zwp_linux_dmabuf_v1 *zwp_linux_dmabuf,
|
||||
uint32_t format)
|
||||
{
|
||||
GstWlDisplay *self = data;
|
||||
|
||||
if (gst_wl_dmabuf_format_to_video_format (format) != GST_VIDEO_FORMAT_UNKNOWN)
|
||||
g_array_append_val (self->dmabuf_formats, format);
|
||||
}
|
||||
|
||||
static const struct zwp_linux_dmabuf_v1_listener dmabuf_listener = {
|
||||
dmabuf_format,
|
||||
};
|
||||
|
||||
gboolean
|
||||
is_shm_format_supported (enum wl_shm_format format_shm, GstWlDisplay * display)
|
||||
{
|
||||
GArray *formats;
|
||||
guint i;
|
||||
|
||||
formats = display->shm_formats;
|
||||
for (i = 0; i < formats->len; i++) {
|
||||
if (g_array_index (formats, uint32_t, i) == format_shm)
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
gboolean
|
||||
is_dmabuf_format_supported (guint format_dmabuf, GstWlDisplay * display)
|
||||
{
|
||||
GArray *formats;
|
||||
guint i;
|
||||
|
||||
formats = display->dmabuf_formats;
|
||||
for (i = 0; i < formats->len; i++) {
|
||||
if (g_array_index (formats, uint32_t, i) == format_dmabuf)
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
static void
|
||||
registry_handle_global (void *data, struct wl_registry *registry,
|
||||
uint32_t id, const char *interface, uint32_t version)
|
||||
|
@ -167,6 +217,10 @@ registry_handle_global (void *data, struct wl_registry *registry,
|
|||
} else if (g_strcmp0 (interface, "wp_viewporter") == 0) {
|
||||
self->viewporter =
|
||||
wl_registry_bind (registry, id, &wp_viewporter_interface, 1);
|
||||
} else if (g_strcmp0 (interface, "zwp_linux_dmabuf_v1") == 0) {
|
||||
self->dmabuf =
|
||||
wl_registry_bind (registry, id, &zwp_linux_dmabuf_v1_interface, 1);
|
||||
zwp_linux_dmabuf_v1_add_listener (self->dmabuf, &dmabuf_listener, self);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -281,6 +335,10 @@ gst_wl_display_new_existing (struct wl_display * display,
|
|||
"display may not work properly.");
|
||||
}
|
||||
|
||||
if (!self->dmabuf) {
|
||||
g_warning ("Could not bind to zwp_linux_dmabuf_v1");
|
||||
}
|
||||
|
||||
self->thread = g_thread_try_new ("GstWlDisplay", gst_wl_display_thread_run,
|
||||
self, &err);
|
||||
if (err) {
|
||||
|
|
|
@ -24,6 +24,7 @@
|
|||
#include <gst/gst.h>
|
||||
#include <wayland-client.h>
|
||||
#include "viewporter-client-protocol.h"
|
||||
#include "linux-dmabuf-unstable-v1-client-protocol.h"
|
||||
|
||||
G_BEGIN_DECLS
|
||||
|
||||
|
@ -52,7 +53,9 @@ struct _GstWlDisplay
|
|||
struct wl_shell *shell;
|
||||
struct wl_shm *shm;
|
||||
struct wp_viewporter *viewporter;
|
||||
struct zwp_linux_dmabuf_v1 *dmabuf;
|
||||
GArray *shm_formats;
|
||||
GArray *dmabuf_formats;
|
||||
|
||||
/* private */
|
||||
gboolean own_display;
|
||||
|
@ -79,6 +82,11 @@ GstWlDisplay *gst_wl_display_new_existing (struct wl_display * display,
|
|||
void gst_wl_display_register_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,
|
||||
GstWlDisplay * display);
|
||||
gboolean is_dmabuf_format_supported (guint format_dmabuf,
|
||||
GstWlDisplay * display);
|
||||
|
||||
G_END_DECLS
|
||||
|
||||
#endif /* __GST_WL_DISPLAY_H__ */
|
||||
|
|
146
ext/wayland/wllinuxdmabuf.c
Normal file
146
ext/wayland/wllinuxdmabuf.c
Normal file
|
@ -0,0 +1,146 @@
|
|||
/* GStreamer Wayland video sink
|
||||
*
|
||||
* Copyright (C) 2016 STMicroelectronics SA
|
||||
* Copyright (C) 2016 Fabien Dessenne <fabien.dessenne@st.com>
|
||||
*
|
||||
* 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 <gst/allocators/gstdmabuf.h>
|
||||
|
||||
#include "wllinuxdmabuf.h"
|
||||
#include "wlvideoformat.h"
|
||||
|
||||
GST_DEBUG_CATEGORY_EXTERN (gstwayland_debug);
|
||||
#define GST_CAT_DEFAULT gstwayland_debug
|
||||
|
||||
typedef struct
|
||||
{
|
||||
GMutex lock;
|
||||
GCond cond;
|
||||
struct wl_buffer *wbuf;
|
||||
} ConstructBufferData;
|
||||
|
||||
static void
|
||||
create_succeeded (void *data, struct zwp_linux_buffer_params_v1 *params,
|
||||
struct wl_buffer *new_buffer)
|
||||
{
|
||||
ConstructBufferData *d = data;
|
||||
|
||||
g_mutex_lock (&d->lock);
|
||||
d->wbuf = new_buffer;
|
||||
zwp_linux_buffer_params_v1_destroy (params);
|
||||
g_cond_signal (&d->cond);
|
||||
g_mutex_unlock (&d->lock);
|
||||
}
|
||||
|
||||
static void
|
||||
create_failed (void *data, struct zwp_linux_buffer_params_v1 *params)
|
||||
{
|
||||
ConstructBufferData *d = data;
|
||||
|
||||
g_mutex_lock (&d->lock);
|
||||
d->wbuf = NULL;
|
||||
zwp_linux_buffer_params_v1_destroy (params);
|
||||
g_cond_signal (&d->cond);
|
||||
g_mutex_unlock (&d->lock);
|
||||
}
|
||||
|
||||
static const struct zwp_linux_buffer_params_v1_listener params_listener = {
|
||||
create_succeeded,
|
||||
create_failed
|
||||
};
|
||||
|
||||
struct wl_buffer *
|
||||
gst_wl_linux_dmabuf_construct_wl_buffer (GstBuffer * buf,
|
||||
GstWlDisplay * display, const GstVideoInfo * info)
|
||||
{
|
||||
GstMemory *mem;
|
||||
int fd, format;
|
||||
guint i, width, height, offset, stride;
|
||||
guint nmem, nplanes, mem_idx, flags = 0;
|
||||
struct zwp_linux_buffer_params_v1 *params;
|
||||
gint64 timeout;
|
||||
ConstructBufferData data;
|
||||
|
||||
mem = gst_buffer_peek_memory (buf, 0);
|
||||
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_mutex_init (&data.lock);
|
||||
g_mutex_lock (&data.lock);
|
||||
|
||||
width = GST_VIDEO_INFO_WIDTH (info);
|
||||
height = GST_VIDEO_INFO_HEIGHT (info);
|
||||
nplanes = GST_VIDEO_INFO_N_PLANES (info);
|
||||
nmem = gst_buffer_n_memory (buf);
|
||||
|
||||
/* Creation and configuration of planes */
|
||||
params = zwp_linux_dmabuf_v1_create_params (display->dmabuf);
|
||||
|
||||
for (i = 0; i < nplanes; i++) {
|
||||
mem_idx = (nmem == nplanes) ? i : 0;
|
||||
fd = gst_dmabuf_memory_get_fd (gst_buffer_peek_memory (buf, mem_idx));
|
||||
offset = GST_VIDEO_INFO_PLANE_OFFSET (info, i);
|
||||
stride = GST_VIDEO_INFO_PLANE_STRIDE (info, i);
|
||||
zwp_linux_buffer_params_v1_add (params, fd, i, offset, stride, 0, 0);
|
||||
}
|
||||
|
||||
if (GST_BUFFER_FLAG_IS_SET (buf, GST_VIDEO_BUFFER_FLAG_INTERLACED)) {
|
||||
GST_DEBUG_OBJECT (mem->allocator, "interlaced buffer");
|
||||
flags = ZWP_LINUX_BUFFER_PARAMS_V1_FLAGS_INTERLACED;
|
||||
|
||||
if (!GST_BUFFER_FLAG_IS_SET (buf, GST_VIDEO_BUFFER_FLAG_TFF)) {
|
||||
GST_DEBUG_OBJECT (mem->allocator, "with bottom field first");
|
||||
flags |= ZWP_LINUX_BUFFER_PARAMS_V1_FLAGS_BOTTOM_FIRST;
|
||||
}
|
||||
}
|
||||
|
||||
/* Request buffer creation */
|
||||
zwp_linux_buffer_params_v1_add_listener (params, ¶ms_listener, &data);
|
||||
zwp_linux_buffer_params_v1_create (params, width, height, format, flags);
|
||||
|
||||
/* Wait for the request answer */
|
||||
wl_display_flush (display->display);
|
||||
data.wbuf = (gpointer) 0x1;
|
||||
timeout = g_get_monotonic_time () + G_TIME_SPAN_SECOND;
|
||||
while (data.wbuf == (gpointer) 0x1) {
|
||||
if (!g_cond_wait_until (&data.cond, &data.lock, timeout)) {
|
||||
GST_ERROR_OBJECT (mem->allocator, "zwp_linux_buffer_params_v1 time out");
|
||||
zwp_linux_buffer_params_v1_destroy (params);
|
||||
data.wbuf = NULL;
|
||||
}
|
||||
}
|
||||
|
||||
if (!data.wbuf) {
|
||||
GST_ERROR_OBJECT (mem->allocator, "can't create linux-dmabuf buffer");
|
||||
} else {
|
||||
GST_DEBUG_OBJECT (mem->allocator, "created linux_dmabuf wl_buffer (%p):"
|
||||
"%dx%d, fmt=%.4s, %d planes",
|
||||
data.wbuf, width, height, (char *) &format, nplanes);
|
||||
}
|
||||
|
||||
g_mutex_unlock (&data.lock);
|
||||
g_mutex_clear (&data.lock);
|
||||
g_cond_clear (&data.cond);
|
||||
|
||||
return data.wbuf;
|
||||
}
|
38
ext/wayland/wllinuxdmabuf.h
Normal file
38
ext/wayland/wllinuxdmabuf.h
Normal file
|
@ -0,0 +1,38 @@
|
|||
/* GStreamer Wayland video sink
|
||||
*
|
||||
* Copyright (C) 2016 STMicroelectronics SA
|
||||
* Copyright (C) 2016 Fabien Dessenne <fabien.dessenne@st.com>
|
||||
*
|
||||
* 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_WL_LINUX_DMABUF_H__
|
||||
#define __GST_WL_LINUX_DMABUF_H__
|
||||
|
||||
#include "gstwaylandsink.h"
|
||||
|
||||
G_BEGIN_DECLS
|
||||
|
||||
#ifndef GST_CAPS_FEATURE_MEMORY_DMABUF
|
||||
#define GST_CAPS_FEATURE_MEMORY_DMABUF "memory:DMABuf"
|
||||
#endif
|
||||
|
||||
struct wl_buffer * gst_wl_linux_dmabuf_construct_wl_buffer (GstBuffer * buf,
|
||||
GstWlDisplay * display, const GstVideoInfo * info);
|
||||
|
||||
G_END_DECLS
|
||||
|
||||
#endif /* __GST_WL_LINUX_DMABUF_H__ */
|
|
@ -146,6 +146,7 @@ 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 (size <= memsize, NULL);
|
||||
g_return_val_if_fail (is_shm_format_supported (format, display), NULL);
|
||||
|
||||
GST_DEBUG_OBJECT (mem->allocator, "Creating wl_buffer of size %"
|
||||
G_GSSIZE_FORMAT " (%d x %d, stride %d), format %s", size, width, height,
|
||||
|
|
|
@ -34,9 +34,15 @@ typedef struct
|
|||
{
|
||||
enum wl_shm_format wl_format;
|
||||
GstVideoFormat gst_format;
|
||||
} wl_VideoFormat;
|
||||
} wl_ShmVideoFormat;
|
||||
|
||||
static const wl_VideoFormat formats[] = {
|
||||
typedef struct
|
||||
{
|
||||
guint wl_format;
|
||||
GstVideoFormat gst_format;
|
||||
} wl_DmabufVideoFormat;
|
||||
|
||||
static const wl_ShmVideoFormat shm_formats[] = {
|
||||
#if G_BYTE_ORDER == G_BIG_ENDIAN
|
||||
{WL_SHM_FORMAT_XRGB8888, GST_VIDEO_FORMAT_xRGB},
|
||||
{WL_SHM_FORMAT_ARGB8888, GST_VIDEO_FORMAT_ARGB},
|
||||
|
@ -77,29 +83,82 @@ static const wl_VideoFormat formats[] = {
|
|||
{WL_SHM_FORMAT_YUV444, GST_VIDEO_FORMAT_v308},
|
||||
};
|
||||
|
||||
static const wl_DmabufVideoFormat dmabuf_formats[] = {
|
||||
#if G_BYTE_ORDER == G_BIG_ENDIAN
|
||||
{DRM_FORMAT_XRGB8888, GST_VIDEO_FORMAT_xRGB},
|
||||
{DRM_FORMAT_ARGB8888, GST_VIDEO_FORMAT_ARGB},
|
||||
{DRM_FORMAT_XBGR8888, GST_VIDEO_FORMAT_xBGR},
|
||||
{DRM_FORMAT_RGBX8888, GST_VIDEO_FORMAT_RGBx},
|
||||
{DRM_FORMAT_BGRX8888, GST_VIDEO_FORMAT_BGRx},
|
||||
{DRM_FORMAT_ABGR8888, GST_VIDEO_FORMAT_ABGR},
|
||||
{DRM_FORMAT_RGBA8888, GST_VIDEO_FORMAT_RGBA},
|
||||
{DRM_FORMAT_BGRA8888, GST_VIDEO_FORMAT_BGRA},
|
||||
{DRM_FORMAT_RGB888, GST_VIDEO_FORMAT_RGB},
|
||||
{DRM_FORMAT_BGR888, GST_VIDEO_FORMAT_BGR},
|
||||
#else
|
||||
{DRM_FORMAT_XRGB8888, GST_VIDEO_FORMAT_BGRx},
|
||||
{DRM_FORMAT_ARGB8888, GST_VIDEO_FORMAT_BGRA},
|
||||
{DRM_FORMAT_XBGR8888, GST_VIDEO_FORMAT_RGBx},
|
||||
{DRM_FORMAT_RGBX8888, GST_VIDEO_FORMAT_xBGR},
|
||||
{DRM_FORMAT_BGRX8888, GST_VIDEO_FORMAT_xRGB},
|
||||
{DRM_FORMAT_ABGR8888, GST_VIDEO_FORMAT_RGBA},
|
||||
{DRM_FORMAT_RGBA8888, GST_VIDEO_FORMAT_ABGR},
|
||||
{DRM_FORMAT_BGRA8888, GST_VIDEO_FORMAT_ARGB},
|
||||
{DRM_FORMAT_RGB888, GST_VIDEO_FORMAT_BGR},
|
||||
{DRM_FORMAT_BGR888, GST_VIDEO_FORMAT_RGB},
|
||||
#endif
|
||||
{DRM_FORMAT_RGB565, GST_VIDEO_FORMAT_RGB16},
|
||||
{DRM_FORMAT_YUYV, GST_VIDEO_FORMAT_YUY2},
|
||||
{DRM_FORMAT_NV12, GST_VIDEO_FORMAT_NV12},
|
||||
};
|
||||
|
||||
enum wl_shm_format
|
||||
gst_video_format_to_wl_shm_format (GstVideoFormat format)
|
||||
{
|
||||
guint i;
|
||||
|
||||
for (i = 0; i < G_N_ELEMENTS (formats); i++)
|
||||
if (formats[i].gst_format == format)
|
||||
return formats[i].wl_format;
|
||||
for (i = 0; i < G_N_ELEMENTS (shm_formats); i++)
|
||||
if (shm_formats[i].gst_format == format)
|
||||
return shm_formats[i].wl_format;
|
||||
|
||||
GST_WARNING ("wayland shm video format not found");
|
||||
return -1;
|
||||
}
|
||||
|
||||
gint
|
||||
gst_video_format_to_wl_dmabuf_format (GstVideoFormat format)
|
||||
{
|
||||
guint i;
|
||||
|
||||
for (i = 0; i < G_N_ELEMENTS (dmabuf_formats); i++)
|
||||
if (dmabuf_formats[i].gst_format == format)
|
||||
return dmabuf_formats[i].wl_format;
|
||||
|
||||
GST_WARNING ("wayland dmabuf video format not found");
|
||||
return -1;
|
||||
}
|
||||
|
||||
GstVideoFormat
|
||||
gst_wl_shm_format_to_video_format (enum wl_shm_format wl_format)
|
||||
{
|
||||
guint i;
|
||||
|
||||
for (i = 0; i < G_N_ELEMENTS (formats); i++)
|
||||
if (formats[i].wl_format == wl_format)
|
||||
return formats[i].gst_format;
|
||||
for (i = 0; i < G_N_ELEMENTS (shm_formats); i++)
|
||||
if (shm_formats[i].wl_format == wl_format)
|
||||
return shm_formats[i].gst_format;
|
||||
|
||||
return GST_VIDEO_FORMAT_UNKNOWN;
|
||||
}
|
||||
|
||||
GstVideoFormat
|
||||
gst_wl_dmabuf_format_to_video_format (guint wl_format)
|
||||
{
|
||||
guint i;
|
||||
|
||||
for (i = 0; i < G_N_ELEMENTS (dmabuf_formats); i++)
|
||||
if (dmabuf_formats[i].wl_format == wl_format)
|
||||
return dmabuf_formats[i].gst_format;
|
||||
|
||||
GST_WARNING ("gst video format not found");
|
||||
return GST_VIDEO_FORMAT_UNKNOWN;
|
||||
}
|
||||
|
||||
|
@ -109,3 +168,10 @@ gst_wl_shm_format_to_string (enum wl_shm_format wl_format)
|
|||
return gst_video_format_to_string
|
||||
(gst_wl_shm_format_to_video_format (wl_format));
|
||||
}
|
||||
|
||||
const gchar *
|
||||
gst_wl_dmabuf_format_to_string (guint wl_format)
|
||||
{
|
||||
return gst_video_format_to_string
|
||||
(gst_wl_dmabuf_format_to_video_format (wl_format));
|
||||
}
|
||||
|
|
|
@ -26,13 +26,16 @@
|
|||
|
||||
#include <wayland-client-protocol.h>
|
||||
#include <gst/video/video.h>
|
||||
#include <drm/drm_fourcc.h>
|
||||
|
||||
G_BEGIN_DECLS
|
||||
|
||||
enum wl_shm_format gst_video_format_to_wl_shm_format (GstVideoFormat format);
|
||||
gint gst_video_format_to_wl_dmabuf_format (GstVideoFormat format);
|
||||
GstVideoFormat gst_wl_shm_format_to_video_format (enum wl_shm_format wl_format);
|
||||
|
||||
GstVideoFormat gst_wl_dmabuf_format_to_video_format (guint wl_format);
|
||||
const gchar *gst_wl_shm_format_to_string (enum wl_shm_format wl_format);
|
||||
const gchar *gst_wl_dmabuf_format_to_string (guint wl_format);
|
||||
|
||||
G_END_DECLS
|
||||
|
||||
|
|
Loading…
Reference in a new issue