mirror of
https://github.com/hyprwm/xdg-desktop-portal-hyprland.git
synced 2024-11-22 14:35:57 +01:00
screencast: pipewire change to self allocation of shm buffers
This commit is contained in:
parent
a33034acce
commit
6cc3a01741
4 changed files with 67 additions and 25 deletions
|
@ -122,6 +122,7 @@ struct xdpw_wlr_output {
|
||||||
};
|
};
|
||||||
|
|
||||||
void randname(char *buf);
|
void randname(char *buf);
|
||||||
|
int anonymous_shm_open(void);
|
||||||
enum spa_video_format xdpw_format_pw_from_wl_shm(enum wl_shm_format format);
|
enum spa_video_format xdpw_format_pw_from_wl_shm(enum wl_shm_format format);
|
||||||
enum spa_video_format xdpw_format_pw_strip_alpha(enum spa_video_format format);
|
enum spa_video_format xdpw_format_pw_strip_alpha(enum spa_video_format format);
|
||||||
|
|
||||||
|
|
|
@ -5,6 +5,8 @@
|
||||||
#include <spa/param/props.h>
|
#include <spa/param/props.h>
|
||||||
#include <spa/param/format-utils.h>
|
#include <spa/param/format-utils.h>
|
||||||
#include <spa/param/video/format-utils.h>
|
#include <spa/param/video/format-utils.h>
|
||||||
|
#include <sys/mman.h>
|
||||||
|
#include <unistd.h>
|
||||||
|
|
||||||
#include "wlr_screencast.h"
|
#include "wlr_screencast.h"
|
||||||
#include "xdpw.h"
|
#include "xdpw.h"
|
||||||
|
@ -145,7 +147,7 @@ static void pwr_handle_stream_param_changed(void *data, uint32_t id,
|
||||||
SPA_PARAM_BUFFERS_size, SPA_POD_Int(cast->simple_frame.size),
|
SPA_PARAM_BUFFERS_size, SPA_POD_Int(cast->simple_frame.size),
|
||||||
SPA_PARAM_BUFFERS_stride, SPA_POD_Int(cast->simple_frame.stride),
|
SPA_PARAM_BUFFERS_stride, SPA_POD_Int(cast->simple_frame.stride),
|
||||||
SPA_PARAM_BUFFERS_align, SPA_POD_Int(XDPW_PWR_ALIGN),
|
SPA_PARAM_BUFFERS_align, SPA_POD_Int(XDPW_PWR_ALIGN),
|
||||||
SPA_PARAM_BUFFERS_dataType,SPA_POD_CHOICE_FLAGS_Int(1<<SPA_DATA_MemPtr));
|
SPA_PARAM_BUFFERS_dataType,SPA_POD_CHOICE_FLAGS_Int(1<<SPA_DATA_MemFd));
|
||||||
|
|
||||||
params[1] = spa_pod_builder_add_object(&b,
|
params[1] = spa_pod_builder_add_object(&b,
|
||||||
SPA_TYPE_OBJECT_ParamMeta, SPA_PARAM_Meta,
|
SPA_TYPE_OBJECT_ParamMeta, SPA_PARAM_Meta,
|
||||||
|
@ -164,28 +166,61 @@ static void pwr_handle_stream_add_buffer(void *data, struct pw_buffer *buffer) {
|
||||||
d = buffer->buffer->datas;
|
d = buffer->buffer->datas;
|
||||||
|
|
||||||
// Select buffer type from negotiation result
|
// Select buffer type from negotiation result
|
||||||
if ((d[0].type & (1u << SPA_DATA_MemPtr)) > 0) {
|
if ((d[0].type & (1u << SPA_DATA_MemFd)) > 0) {
|
||||||
d[0].type = SPA_DATA_MemPtr;
|
d[0].type = SPA_DATA_MemFd;
|
||||||
} else {
|
} else {
|
||||||
logprint(ERROR, "pipewire: unsupported buffer type");
|
logprint(ERROR, "pipewire: unsupported buffer type");
|
||||||
cast->err = 1;
|
cast->err = 1;
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
logprint(TRACE, "pipewire: selected buffertype %u", d[0].type);
|
||||||
// Prepare buffer for choosen type
|
// Prepare buffer for choosen type
|
||||||
if (d[0].type == SPA_DATA_MemPtr) {
|
if (d[0].type == SPA_DATA_MemFd) {
|
||||||
d[0].maxsize = cast->simple_frame.size;
|
d[0].maxsize = cast->simple_frame.size;
|
||||||
d[0].mapoffset = 0;
|
d[0].mapoffset = 0;
|
||||||
d[0].chunk->size = cast->simple_frame.size;
|
d[0].chunk->size = cast->simple_frame.size;
|
||||||
d[0].chunk->stride = cast->simple_frame.stride;
|
d[0].chunk->stride = cast->simple_frame.stride;
|
||||||
d[0].chunk->offset = 0;
|
d[0].chunk->offset = 0;
|
||||||
d[0].flags = 0;
|
d[0].flags = 0;
|
||||||
d[0].fd = -1;
|
d[0].fd = anonymous_shm_open();
|
||||||
|
|
||||||
|
if (d[0].fd == -1) {
|
||||||
|
logprint(ERROR, "pipewire: unable to create anonymous filedescriptor");
|
||||||
|
cast->err = 1;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (ftruncate(d[0].fd, d[0].maxsize) < 0) {
|
||||||
|
logprint(ERROR, "pipewire: unable to truncate filedescriptor");
|
||||||
|
close(d[0].fd);
|
||||||
|
d[0].fd = -1;
|
||||||
|
cast->err = 1;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
// mmap buffer, so we can use the data_ptr in on_process
|
||||||
|
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) {
|
||||||
|
logprint(ERROR, "pipewire: unable to mmap memory");
|
||||||
|
cast->err = 1;
|
||||||
|
return;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
static void pwr_handle_stream_remove_buffer(void *data, struct pw_buffer *buffer) {
|
static void pwr_handle_stream_remove_buffer(void *data, struct pw_buffer *buffer) {
|
||||||
logprint(TRACE, "pipewire: remove buffer event handle");
|
logprint(TRACE, "pipewire: remove buffer event handle");
|
||||||
|
|
||||||
|
struct spa_data *d = buffer->buffer->datas;
|
||||||
|
switch (d[0].type) {
|
||||||
|
case SPA_DATA_MemFd:
|
||||||
|
munmap(d[0].data, d[0].maxsize);
|
||||||
|
close(d[0].fd);
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
break;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
static const struct pw_stream_events pwr_stream_events = {
|
static const struct pw_stream_events pwr_stream_events = {
|
||||||
|
@ -250,7 +285,8 @@ void xdpw_pwr_stream_create(struct xdpw_screencast_instance *cast) {
|
||||||
pw_stream_connect(cast->stream,
|
pw_stream_connect(cast->stream,
|
||||||
PW_DIRECTION_OUTPUT,
|
PW_DIRECTION_OUTPUT,
|
||||||
PW_ID_ANY,
|
PW_ID_ANY,
|
||||||
PW_STREAM_FLAG_DRIVER,
|
(PW_STREAM_FLAG_DRIVER |
|
||||||
|
PW_STREAM_FLAG_ALLOC_BUFFERS),
|
||||||
¶m, 1);
|
¶m, 1);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -1,5 +1,10 @@
|
||||||
#include "screencast_common.h"
|
#include "screencast_common.h"
|
||||||
#include <assert.h>
|
#include <assert.h>
|
||||||
|
#include <fcntl.h>
|
||||||
|
#include <string.h>
|
||||||
|
#include <sys/mman.h>
|
||||||
|
#include <sys/stat.h>
|
||||||
|
#include <unistd.h>
|
||||||
|
|
||||||
void randname(char *buf) {
|
void randname(char *buf) {
|
||||||
struct timespec ts;
|
struct timespec ts;
|
||||||
|
@ -12,6 +17,25 @@ void randname(char *buf) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
int anonymous_shm_open(void) {
|
||||||
|
char name[] = "/xdpw-shm-XXXXXX";
|
||||||
|
int retries = 100;
|
||||||
|
|
||||||
|
do {
|
||||||
|
randname(name + strlen(name) - 6);
|
||||||
|
|
||||||
|
--retries;
|
||||||
|
// shm_open guarantees that O_CLOEXEC is set
|
||||||
|
int fd = shm_open(name, O_RDWR | O_CREAT | O_EXCL, S_IRUSR | S_IWUSR);
|
||||||
|
if (fd >= 0) {
|
||||||
|
shm_unlink(name);
|
||||||
|
return fd;
|
||||||
|
}
|
||||||
|
} while (retries > 0 && errno == EEXIST);
|
||||||
|
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
enum spa_video_format xdpw_format_pw_from_wl_shm(enum wl_shm_format format) {
|
enum spa_video_format xdpw_format_pw_from_wl_shm(enum wl_shm_format format) {
|
||||||
switch (format) {
|
switch (format) {
|
||||||
case WL_SHM_FORMAT_ARGB8888:
|
case WL_SHM_FORMAT_ARGB8888:
|
||||||
|
|
|
@ -61,25 +61,6 @@ void xdpw_wlr_frame_free(struct xdpw_screencast_instance *cast) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
static int anonymous_shm_open(void) {
|
|
||||||
char name[] = "/xdpw-shm-XXXXXX";
|
|
||||||
int retries = 100;
|
|
||||||
|
|
||||||
do {
|
|
||||||
randname(name + strlen(name) - 6);
|
|
||||||
|
|
||||||
--retries;
|
|
||||||
// shm_open guarantees that O_CLOEXEC is set
|
|
||||||
int fd = shm_open(name, O_RDWR | O_CREAT | O_EXCL, S_IRUSR | S_IWUSR);
|
|
||||||
if (fd >= 0) {
|
|
||||||
shm_unlink(name);
|
|
||||||
return fd;
|
|
||||||
}
|
|
||||||
} while (retries > 0 && errno == EEXIST);
|
|
||||||
|
|
||||||
return -1;
|
|
||||||
}
|
|
||||||
|
|
||||||
static struct wl_buffer *create_shm_buffer(struct xdpw_screencast_instance *cast,
|
static struct wl_buffer *create_shm_buffer(struct xdpw_screencast_instance *cast,
|
||||||
enum wl_shm_format fmt, int width, int height, int stride,
|
enum wl_shm_format fmt, int width, int height, int stride,
|
||||||
void **data_out) {
|
void **data_out) {
|
||||||
|
|
Loading…
Reference in a new issue