Skip to content

Commit df10621

Browse files
committed
capture/pipewire: Workaround for frames marked as non-readable
On Arch with wlroots-git, sway-git and nvidia 595.45.04 data buffers are not marked as SPA_DATA_FLAG_READABLE for some reason and PW mmaps them with no read access leading to segfaults.
1 parent d94b823 commit df10621

File tree

1 file changed

+16
-1
lines changed

1 file changed

+16
-1
lines changed

src/video_capture/pipewire.cpp

Lines changed: 16 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -53,6 +53,7 @@
5353
#include <spa/param/video/format-utils.h>
5454
#include <spa/param/props.h>
5555
#include <spa/debug/types.h>
56+
#include <sys/mman.h>
5657

5758
#include "debug.h"
5859
#include "lib_common.h"
@@ -222,8 +223,19 @@ static void pw_frame_to_uv_frame_memcpy(video_frame *dst, spa_buffer *src, spa_v
222223
auto linesize = vc_get_linesize(width, dst->color_spec);
223224
auto skip = vc_get_linesize(start_x, dst->color_spec);
224225
bool swap_red_blue = fmt == SPA_VIDEO_FORMAT_BGRA || fmt == SPA_VIDEO_FORMAT_BGRx; //TODO
226+
void *data_ptr = src->datas[0].data;
227+
void *mmap_ptr = nullptr;
228+
if(!SPA_FLAG_IS_SET(src->datas[0].flags, SPA_DATA_FLAG_READABLE)
229+
#ifdef SPA_DATA_FLAG_MAPPABLE
230+
&& SPA_FLAG_IS_SET(src->datas[0].flags, SPA_DATA_FLAG_MAPPABLE)
231+
#endif
232+
){
233+
log_msg(LOG_LEVEL_WARNING, MOD_NAME "Buffer marked as not readable, but trying to map it as readable anyways!\n");
234+
mmap_ptr = mmap(nullptr, linesize * height, PROT_READ, MAP_SHARED, src->datas[0].fd, 0);
235+
data_ptr = mmap_ptr;
236+
}
225237
for(unsigned i = 0; i < height; i++){
226-
auto src_p = static_cast<unsigned char *>(src->datas[0].data) + offset + skip + stride * (i + start_y);
238+
auto src_p = static_cast<unsigned char *>(data_ptr) + offset + skip + stride * (i + start_y);
227239
auto dst_p = reinterpret_cast<unsigned char *>(dst->tiles[0].data) + linesize * i;
228240
/* It would probably be better to have separate functions for
229241
* pipweire to uv frame conversions like lavd has. For now,
@@ -234,6 +246,9 @@ static void pw_frame_to_uv_frame_memcpy(video_frame *dst, spa_buffer *src, spa_v
234246
else
235247
memcpy(dst_p, src_p, linesize);
236248
}
249+
if(mmap_ptr){
250+
munmap(mmap_ptr, linesize * height);
251+
}
237252

238253
dst->tiles[0].width = width;
239254
dst->tiles[0].height = height;

0 commit comments

Comments
 (0)