Commit 6e39724b authored by Georges Basile Stavracas Neto's avatar Georges Basile Stavracas Neto
Browse files

pipewire: Protect against failing to setup DMA-BUF texture

Even with the stream source being able to send DMA-BUF buffers, the
client can, for various reasons, fail to setup a GL texture from it.
In those cases, fallback to the slower download + upload path.
parent 141c6965
......@@ -4,6 +4,7 @@ sources = files(
'desktop-capture.c',
'obs-xdg-portal.c',
'pipewire.c',
'utils.c',
'window-capture.c',
)
......
......@@ -20,10 +20,13 @@
#include "pipewire.h"
#include "utils.h"
#include <gio/gio.h>
#include <gio/gunixfdlist.h>
#include <fcntl.h>
#include <linux/dma-buf.h>
#include <pipewire/pipewire.h>
#include <spa/param/video/format-utils.h>
#include <spa/debug/types.h>
......@@ -282,7 +285,9 @@ on_process_cb (void *user_data)
enum gs_color_format obs_format;
struct spa_buffer *buffer;
struct pw_buffer *b;
bool dmabuf_creation_failed;
bool has_buffer;
bool is_dmabuf;
/* Find the most recent buffer */
b = NULL;
......@@ -312,10 +317,11 @@ on_process_cb (void *user_data)
spa_pixel_format_to_obs_pixel_format (xdg->format.info.raw.format,
&obs_format);
if (!has_buffer)
{
/* Do nothing; empty chunk means this is a metadata-only frame */
}
else if (buffer->datas[0].type == SPA_DATA_DmaBuf)
goto read_metadata;
is_dmabuf = buffer->datas[0].type == SPA_DATA_DmaBuf;
dmabuf_creation_failed = false;
if (is_dmabuf)
{
uint32_t offsets[1];
uint32_t strides[1];
......@@ -342,11 +348,16 @@ on_process_cb (void *user_data)
strides,
offsets,
NULL);
dmabuf_creation_failed = xdg->texture == NULL;
}
else
if (!is_dmabuf || dmabuf_creation_failed)
{
blog (LOG_DEBUG, "[pipewire] Buffer has memory texture");
if (is_dmabuf)
sync_dma_buf (buffer->datas[0].fd, DMA_BUF_SYNC_START);
g_clear_pointer (&xdg->texture, gs_texture_destroy);
xdg->texture =
gs_texture_create (xdg->format.info.raw.size.width,
......@@ -355,6 +366,9 @@ on_process_cb (void *user_data)
1,
(const uint8_t **)&buffer->datas[0].data,
GS_DYNAMIC);
if (is_dmabuf)
sync_dma_buf (buffer->datas[0].fd, DMA_BUF_SYNC_START);
}
/* Video Crop */
......@@ -383,6 +397,8 @@ on_process_cb (void *user_data)
}
}
read_metadata:
/* Cursor */
cursor = spa_buffer_find_meta_data (buffer, SPA_META_Cursor, sizeof (*cursor));
xdg->cursor.valid = cursor && spa_meta_cursor_is_valid (cursor);
......
/* utils.c
*
* Copyright 2020 Georges Basile Stavracas Neto <georges.stavracas@gmail.com>
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program 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 General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*
* SPDX-License-Identifier: GPL-3.0-or-later
*/
#include "utils.h"
#include <linux/dma-buf.h>
#include <sys/ioctl.h>
#include <errno.h>
#include <obs/obs-module.h>
void
sync_dma_buf (int fd,
uint64_t flags)
{
struct dma_buf_sync sync = { 0 };
sync.flags = flags | DMA_BUF_SYNC_READ;
while (true)
{
int ret;
ret = ioctl (fd, DMA_BUF_IOCTL_SYNC, &sync);
if (ret == -1 && errno == EINTR)
{
continue;
}
else if (ret == -1)
{
blog (LOG_WARNING, "Failed to synchronize DMA buffer: %m");
break;
}
else
{
break;
}
}
}
/* utils.h
*
* Copyright 2020 Georges Basile Stavracas Neto <georges.stavracas@gmail.com>
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program 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 General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*
* SPDX-License-Identifier: GPL-3.0-or-later
*/
#pragma once
#include <stdint.h>
void sync_dma_buf (int fd,
uint64_t flags);
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment