[mutter/gbsneto/dmabuf-screencast: 6/8] screen-cast-stream-src: Allow exporting DMABufs
- From: Georges Basile Stavracas Neto <gbsneto src gnome org>
- To: commits-list gnome org
- Cc:
- Subject: [mutter/gbsneto/dmabuf-screencast: 6/8] screen-cast-stream-src: Allow exporting DMABufs
- Date: Mon, 24 Feb 2020 17:01:02 +0000 (UTC)
commit f6bebcfcb1e7ba4422f2caa8ba5df9ffe2bff8fa
Author: Georges Basile Stavracas Neto <georges stavracas gmail com>
Date: Mon Dec 9 10:10:40 2019 -0300
screen-cast-stream-src: Allow exporting DMABufs
Implement add_buffer and remove_buffer, and fallback to a memfd if
DMA buffer exporting fails.
https://gitlab.gnome.org/GNOME/mutter/-/merge_requests/1086
src/backends/meta-screen-cast-stream-src.c | 100 ++++++++++++++++++++++++++++-
1 file changed, 98 insertions(+), 2 deletions(-)
---
diff --git a/src/backends/meta-screen-cast-stream-src.c b/src/backends/meta-screen-cast-stream-src.c
index db68b5be4..f49106e53 100644
--- a/src/backends/meta-screen-cast-stream-src.c
+++ b/src/backends/meta-screen-cast-stream-src.c
@@ -25,6 +25,7 @@
#include "backends/meta-screen-cast-stream-src.h"
#include <errno.h>
+#include <fcntl.h>
#include <pipewire/pipewire.h>
#include <spa/param/props.h>
#include <spa/param/format-utils.h>
@@ -473,7 +474,8 @@ meta_screen_cast_stream_src_maybe_record_frame (MetaScreenCastStreamSrc *src)
return;
}
- if (meta_screen_cast_stream_src_record_frame (src, data))
+ if (spa_buffer->datas[0].type != SPA_DATA_DmaBuf &&
+ meta_screen_cast_stream_src_record_frame (src, data))
{
struct spa_meta_region *spa_meta_video_crop;
@@ -642,10 +644,104 @@ on_stream_param_changed (void *data,
pw_stream_update_params (priv->pipewire_stream, params, G_N_ELEMENTS (params));
}
+static void
+on_stream_add_buffer (void *data,
+ struct pw_buffer *buffer)
+{
+ MetaScreenCastStreamSrc *src = data;
+ MetaScreenCastStreamSrcPrivate *priv =
+ meta_screen_cast_stream_src_get_instance_private (src);
+ CoglOnscreenDmabufHandle *dmabuf_handle;
+ struct spa_buffer *buf = buffer->buffer;
+ struct spa_data *d;
+ const int bpp = 4;
+ int stride;
+
+ d = buf->datas;
+ dmabuf_handle = meta_screen_cast_stream_src_capture_dmabuf (src);
+
+ stride = SPA_ROUND_UP_N (priv->video_format.size.width * bpp, 4);
+
+ d[0].mapoffset = 0;
+ d[0].maxsize = stride * priv->video_format.size.height;
+
+ if (dmabuf_handle)
+ {
+ d[0].type = SPA_DATA_DmaBuf;
+ d[0].flags = SPA_DATA_FLAG_READWRITE;
+ d[0].fd = cogl_onscreen_dmabuf_handle_get_fd (dmabuf_handle);
+ d[0].data = NULL;
+
+ g_hash_table_insert (priv->dmabuf_handles,
+ GINT_TO_POINTER (d[0].fd),
+ dmabuf_handle);
+ }
+ else
+ {
+ unsigned int seals;
+
+ /* Fallback to a memfd buffer */
+ d[0].type = SPA_DATA_MemFd;
+ d[0].flags = SPA_DATA_FLAG_READWRITE;
+ d[0].fd = memfd_create ("video-src-memfd", MFD_CLOEXEC | MFD_ALLOW_SEALING);
+ if (d[0].fd == -1)
+ {
+ g_critical ("Can't create memfd: %m");
+ return;
+ }
+ d[0].mapoffset = 0;
+ d[0].maxsize = stride * priv->video_format.size.height;
+
+ if (ftruncate (d[0].fd, d[0].maxsize) < 0)
+ {
+ g_critical ("Can't truncate to %d: %m", d[0].maxsize);
+ return;
+ }
+
+ seals = F_SEAL_GROW | F_SEAL_SHRINK | F_SEAL_SEAL;
+ if (fcntl (d[0].fd, F_ADD_SEALS, seals) == -1)
+ g_warning ("Failed to add seals: %m");
+
+ d[0].data = mmap (NULL, d[0].maxsize, PROT_READ | PROT_WRITE,
+ MAP_SHARED, d[0].fd, d[0].mapoffset);
+ if (d[0].data == MAP_FAILED)
+ {
+ g_critical ("Failed to mmap memory: %m");
+ return;
+ }
+ }
+}
+
+static void
+on_stream_remove_buffer (void *data,
+ struct pw_buffer *buffer)
+{
+ MetaScreenCastStreamSrc *src = data;
+ MetaScreenCastStreamSrcPrivate *priv =
+ meta_screen_cast_stream_src_get_instance_private (src);
+ struct spa_buffer *buf = buffer->buffer;
+ struct spa_data *d;
+
+ d = buf->datas;
+
+ if (d[0].type == SPA_DATA_DmaBuf)
+ {
+ if (!g_hash_table_remove (priv->dmabuf_handles, GINT_TO_POINTER (d[0].fd)))
+ g_critical ("Failed to remove non-exported DMA buffer");
+ }
+ else if (d[0].type == SPA_DATA_MemFd)
+ {
+ munmap (d[0].data, d[0].maxsize);
+ close (d[0].fd);
+ }
+}
+
static const struct pw_stream_events stream_events = {
PW_VERSION_STREAM_EVENTS,
.state_changed = on_stream_state_changed,
.param_changed = on_stream_param_changed,
+ .add_buffer = on_stream_add_buffer,
+ .remove_buffer = on_stream_remove_buffer,
};
static struct pw_stream *
@@ -710,7 +806,7 @@ create_pipewire_stream (MetaScreenCastStreamSrc *src,
PW_DIRECTION_OUTPUT,
SPA_ID_INVALID,
(PW_STREAM_FLAG_DRIVER |
- PW_STREAM_FLAG_MAP_BUFFERS),
+ PW_STREAM_FLAG_ALLOC_BUFFERS),
params, G_N_ELEMENTS (params));
if (result != 0)
{
[
Date Prev][
Date Next] [
Thread Prev][
Thread Next]
[
Thread Index]
[
Date Index]
[
Author Index]