mirror of
https://github.com/brl/mutter.git
synced 2024-11-23 16:40:41 -05:00
screen-cast: Update to PipeWire 0.3 API
Update to 0.3 API [jadahl: update Dockerfile to include new enough pipewire] Fixes: https://gitlab.gnome.org/GNOME/mutter/issues/1051 https://gitlab.gnome.org/GNOME/mutter/merge_requests/1062
This commit is contained in:
parent
f5a28aa9e4
commit
c5d2fc856a
@ -11,6 +11,7 @@ RUN dnf -y update && dnf -y upgrade && \
|
|||||||
dnf install -y 'dnf-command(builddep)' && \
|
dnf install -y 'dnf-command(builddep)' && \
|
||||||
dnf install -y 'dnf-command(copr)' && \
|
dnf install -y 'dnf-command(copr)' && \
|
||||||
dnf copr enable -y fmuellner/gnome-shell-ci && \
|
dnf copr enable -y fmuellner/gnome-shell-ci && \
|
||||||
|
dnf copr enable -y jadahl/mutter-ci && \
|
||||||
dnf -y update && dnf -y upgrade && \
|
dnf -y update && dnf -y upgrade && \
|
||||||
|
|
||||||
dnf builddep -y mutter && \
|
dnf builddep -y mutter && \
|
||||||
@ -26,4 +27,6 @@ RUN dnf -y update && dnf -y upgrade && \
|
|||||||
dnf remove -y gnome-bluetooth-libs-devel dbus-glib-devel upower-devel python3-devel && \
|
dnf remove -y gnome-bluetooth-libs-devel dbus-glib-devel upower-devel python3-devel && \
|
||||||
dnf remove -y --noautoremove mutter mutter-devel && \
|
dnf remove -y --noautoremove mutter mutter-devel && \
|
||||||
|
|
||||||
|
dnf upgrade -y 'pkgconfig(libpipewire-0.3)' && \
|
||||||
|
|
||||||
dnf clean all
|
dnf clean all
|
||||||
|
@ -50,7 +50,7 @@ libinput_req = '>= 1.7'
|
|||||||
gbm_req = '>= 10.3'
|
gbm_req = '>= 10.3'
|
||||||
|
|
||||||
# screen cast version requirements
|
# screen cast version requirements
|
||||||
libpipewire_req = '>= 0.2.5'
|
libpipewire_req = '>= 0.3.0'
|
||||||
|
|
||||||
gnome = import('gnome')
|
gnome = import('gnome')
|
||||||
pkg = import('pkgconfig')
|
pkg = import('pkgconfig')
|
||||||
@ -241,7 +241,7 @@ endif
|
|||||||
|
|
||||||
have_remote_desktop = get_option('remote_desktop')
|
have_remote_desktop = get_option('remote_desktop')
|
||||||
if have_remote_desktop
|
if have_remote_desktop
|
||||||
libpipewire_dep = dependency('libpipewire-0.2', version: libpipewire_req)
|
libpipewire_dep = dependency('libpipewire-0.3', version: libpipewire_req)
|
||||||
endif
|
endif
|
||||||
|
|
||||||
have_introspection = get_option('introspection')
|
have_introspection = get_option('introspection')
|
||||||
|
@ -29,6 +29,7 @@
|
|||||||
#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 <spa/utils/result.h>
|
||||||
#include <stdint.h>
|
#include <stdint.h>
|
||||||
#include <sys/mman.h>
|
#include <sys/mman.h>
|
||||||
|
|
||||||
@ -62,15 +63,6 @@ enum
|
|||||||
|
|
||||||
static guint signals[N_SIGNALS];
|
static guint signals[N_SIGNALS];
|
||||||
|
|
||||||
typedef struct _MetaSpaType
|
|
||||||
{
|
|
||||||
struct spa_type_media_type media_type;
|
|
||||||
struct spa_type_media_subtype media_subtype;
|
|
||||||
struct spa_type_format_video format_video;
|
|
||||||
struct spa_type_video_format video_format;
|
|
||||||
uint32_t meta_cursor;
|
|
||||||
} MetaSpaType;
|
|
||||||
|
|
||||||
typedef struct _MetaPipeWireSource
|
typedef struct _MetaPipeWireSource
|
||||||
{
|
{
|
||||||
GSource base;
|
GSource base;
|
||||||
@ -82,19 +74,19 @@ typedef struct _MetaScreenCastStreamSrcPrivate
|
|||||||
{
|
{
|
||||||
MetaScreenCastStream *stream;
|
MetaScreenCastStream *stream;
|
||||||
|
|
||||||
|
struct pw_context *pipewire_context;
|
||||||
struct pw_core *pipewire_core;
|
struct pw_core *pipewire_core;
|
||||||
struct pw_remote *pipewire_remote;
|
|
||||||
struct pw_type *pipewire_type;
|
|
||||||
MetaPipeWireSource *pipewire_source;
|
MetaPipeWireSource *pipewire_source;
|
||||||
struct spa_hook pipewire_remote_listener;
|
struct spa_hook pipewire_core_listener;
|
||||||
|
|
||||||
gboolean is_enabled;
|
gboolean is_enabled;
|
||||||
|
|
||||||
struct pw_stream *pipewire_stream;
|
struct pw_stream *pipewire_stream;
|
||||||
struct spa_hook pipewire_stream_listener;
|
struct spa_hook pipewire_stream_listener;
|
||||||
|
uint32_t node_id;
|
||||||
|
|
||||||
MetaSpaType spa_type;
|
|
||||||
struct spa_video_info_raw video_format;
|
struct spa_video_info_raw video_format;
|
||||||
|
int video_stride;
|
||||||
|
|
||||||
uint64_t last_frame_timestamp_us;
|
uint64_t last_frame_timestamp_us;
|
||||||
|
|
||||||
@ -112,8 +104,6 @@ G_DEFINE_TYPE_WITH_CODE (MetaScreenCastStreamSrc,
|
|||||||
meta_screen_cast_stream_src_init_initable_iface)
|
meta_screen_cast_stream_src_init_initable_iface)
|
||||||
G_ADD_PRIVATE (MetaScreenCastStreamSrc))
|
G_ADD_PRIVATE (MetaScreenCastStreamSrc))
|
||||||
|
|
||||||
#define PROP_RANGE(min, max) 2, (min), (max)
|
|
||||||
|
|
||||||
static void
|
static void
|
||||||
meta_screen_cast_stream_src_get_specs (MetaScreenCastStreamSrc *src,
|
meta_screen_cast_stream_src_get_specs (MetaScreenCastStreamSrc *src,
|
||||||
int *width,
|
int *width,
|
||||||
@ -286,9 +276,6 @@ meta_screen_cast_stream_src_set_empty_cursor_sprite_metadata (MetaScreenCastStre
|
|||||||
int x,
|
int x,
|
||||||
int y)
|
int y)
|
||||||
{
|
{
|
||||||
MetaScreenCastStreamSrcPrivate *priv =
|
|
||||||
meta_screen_cast_stream_src_get_instance_private (src);
|
|
||||||
MetaSpaType *spa_type = &priv->spa_type;
|
|
||||||
struct spa_meta_bitmap *spa_meta_bitmap;
|
struct spa_meta_bitmap *spa_meta_bitmap;
|
||||||
|
|
||||||
spa_meta_cursor->id = 1;
|
spa_meta_cursor->id = 1;
|
||||||
@ -300,7 +287,7 @@ meta_screen_cast_stream_src_set_empty_cursor_sprite_metadata (MetaScreenCastStre
|
|||||||
spa_meta_bitmap = SPA_MEMBER (spa_meta_cursor,
|
spa_meta_bitmap = SPA_MEMBER (spa_meta_cursor,
|
||||||
spa_meta_cursor->bitmap_offset,
|
spa_meta_cursor->bitmap_offset,
|
||||||
struct spa_meta_bitmap);
|
struct spa_meta_bitmap);
|
||||||
spa_meta_bitmap->format = spa_type->video_format.RGBA;
|
spa_meta_bitmap->format = SPA_VIDEO_FORMAT_RGBA;
|
||||||
spa_meta_bitmap->offset = sizeof (struct spa_meta_bitmap);
|
spa_meta_bitmap->offset = sizeof (struct spa_meta_bitmap);
|
||||||
|
|
||||||
spa_meta_cursor->hotspot.x = 0;
|
spa_meta_cursor->hotspot.x = 0;
|
||||||
@ -317,9 +304,6 @@ meta_screen_cast_stream_src_set_cursor_sprite_metadata (MetaScreenCastStreamSrc
|
|||||||
int y,
|
int y,
|
||||||
float scale)
|
float scale)
|
||||||
{
|
{
|
||||||
MetaScreenCastStreamSrcPrivate *priv =
|
|
||||||
meta_screen_cast_stream_src_get_instance_private (src);
|
|
||||||
MetaSpaType *spa_type = &priv->spa_type;
|
|
||||||
CoglTexture *cursor_texture;
|
CoglTexture *cursor_texture;
|
||||||
struct spa_meta_bitmap *spa_meta_bitmap;
|
struct spa_meta_bitmap *spa_meta_bitmap;
|
||||||
int hotspot_x, hotspot_y;
|
int hotspot_x, hotspot_y;
|
||||||
@ -346,7 +330,7 @@ meta_screen_cast_stream_src_set_cursor_sprite_metadata (MetaScreenCastStreamSrc
|
|||||||
spa_meta_bitmap = SPA_MEMBER (spa_meta_cursor,
|
spa_meta_bitmap = SPA_MEMBER (spa_meta_cursor,
|
||||||
spa_meta_cursor->bitmap_offset,
|
spa_meta_cursor->bitmap_offset,
|
||||||
struct spa_meta_bitmap);
|
struct spa_meta_bitmap);
|
||||||
spa_meta_bitmap->format = spa_type->video_format.RGBA;
|
spa_meta_bitmap->format = SPA_VIDEO_FORMAT_RGBA;
|
||||||
spa_meta_bitmap->offset = sizeof (struct spa_meta_bitmap);
|
spa_meta_bitmap->offset = sizeof (struct spa_meta_bitmap);
|
||||||
|
|
||||||
meta_cursor_sprite_get_hotspot (cursor_sprite, &hotspot_x, &hotspot_y);
|
meta_cursor_sprite_get_hotspot (cursor_sprite, &hotspot_x, &hotspot_y);
|
||||||
@ -382,12 +366,10 @@ static void
|
|||||||
add_cursor_metadata (MetaScreenCastStreamSrc *src,
|
add_cursor_metadata (MetaScreenCastStreamSrc *src,
|
||||||
struct spa_buffer *spa_buffer)
|
struct spa_buffer *spa_buffer)
|
||||||
{
|
{
|
||||||
MetaScreenCastStreamSrcPrivate *priv =
|
|
||||||
meta_screen_cast_stream_src_get_instance_private (src);
|
|
||||||
MetaSpaType *spa_type = &priv->spa_type;
|
|
||||||
struct spa_meta_cursor *spa_meta_cursor;
|
struct spa_meta_cursor *spa_meta_cursor;
|
||||||
|
|
||||||
spa_meta_cursor = spa_buffer_find_meta (spa_buffer, spa_type->meta_cursor);
|
spa_meta_cursor = spa_buffer_find_meta_data (spa_buffer, SPA_META_Cursor,
|
||||||
|
sizeof (*spa_meta_cursor));
|
||||||
if (spa_meta_cursor)
|
if (spa_meta_cursor)
|
||||||
meta_screen_cast_stream_src_set_cursor_metadata (src, spa_meta_cursor);
|
meta_screen_cast_stream_src_set_cursor_metadata (src, spa_meta_cursor);
|
||||||
}
|
}
|
||||||
@ -447,14 +429,14 @@ meta_screen_cast_stream_src_maybe_record_frame (MetaScreenCastStreamSrc *src)
|
|||||||
{
|
{
|
||||||
data = spa_buffer->datas[0].data;
|
data = spa_buffer->datas[0].data;
|
||||||
}
|
}
|
||||||
else if (spa_buffer->datas[0].type == priv->pipewire_type->data.MemFd)
|
else if (spa_buffer->datas[0].type == SPA_DATA_MemFd)
|
||||||
{
|
{
|
||||||
map = mmap (NULL, spa_buffer->datas[0].maxsize + spa_buffer->datas[0].mapoffset,
|
map = mmap (NULL, spa_buffer->datas[0].maxsize + spa_buffer->datas[0].mapoffset,
|
||||||
PROT_READ | PROT_WRITE, MAP_SHARED,
|
PROT_READ | PROT_WRITE, MAP_SHARED,
|
||||||
spa_buffer->datas[0].fd, 0);
|
spa_buffer->datas[0].fd, 0);
|
||||||
if (map == MAP_FAILED)
|
if (map == MAP_FAILED)
|
||||||
{
|
{
|
||||||
g_warning ("Failed to mmap pipewire stream buffer: %s\n",
|
g_warning ("Failed to mmap pipewire stream buffer: %s",
|
||||||
strerror (errno));
|
strerror (errno));
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
@ -469,28 +451,30 @@ meta_screen_cast_stream_src_maybe_record_frame (MetaScreenCastStreamSrc *src)
|
|||||||
|
|
||||||
if (meta_screen_cast_stream_src_record_frame (src, data))
|
if (meta_screen_cast_stream_src_record_frame (src, data))
|
||||||
{
|
{
|
||||||
struct spa_meta_video_crop *spa_meta_video_crop;
|
struct spa_meta_region *spa_meta_video_crop;
|
||||||
|
|
||||||
spa_buffer->datas[0].chunk->size = spa_buffer->datas[0].maxsize;
|
spa_buffer->datas[0].chunk->size = spa_buffer->datas[0].maxsize;
|
||||||
|
spa_buffer->datas[0].chunk->stride = priv->video_stride;
|
||||||
|
|
||||||
/* Update VideoCrop if needed */
|
/* Update VideoCrop if needed */
|
||||||
spa_meta_video_crop =
|
spa_meta_video_crop =
|
||||||
spa_buffer_find_meta (spa_buffer, priv->pipewire_type->meta.VideoCrop);
|
spa_buffer_find_meta_data (spa_buffer, SPA_META_VideoCrop,
|
||||||
|
sizeof (*spa_meta_video_crop));
|
||||||
if (spa_meta_video_crop)
|
if (spa_meta_video_crop)
|
||||||
{
|
{
|
||||||
if (meta_screen_cast_stream_src_get_videocrop (src, &crop_rect))
|
if (meta_screen_cast_stream_src_get_videocrop (src, &crop_rect))
|
||||||
{
|
{
|
||||||
spa_meta_video_crop->x = crop_rect.x;
|
spa_meta_video_crop->region.position.x = crop_rect.x;
|
||||||
spa_meta_video_crop->y = crop_rect.y;
|
spa_meta_video_crop->region.position.y = crop_rect.y;
|
||||||
spa_meta_video_crop->width = crop_rect.width;
|
spa_meta_video_crop->region.size.width = crop_rect.width;
|
||||||
spa_meta_video_crop->height = crop_rect.height;
|
spa_meta_video_crop->region.size.height = crop_rect.height;
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
spa_meta_video_crop->x = 0;
|
spa_meta_video_crop->region.position.x = 0;
|
||||||
spa_meta_video_crop->y = 0;
|
spa_meta_video_crop->region.position.y = 0;
|
||||||
spa_meta_video_crop->width = priv->stream_width;
|
spa_meta_video_crop->region.size.width = priv->stream_width;
|
||||||
spa_meta_video_crop->height = priv->stream_height;
|
spa_meta_video_crop->region.size.height = priv->stream_height;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -555,7 +539,6 @@ on_stream_state_changed (void *data,
|
|||||||
MetaScreenCastStreamSrc *src = data;
|
MetaScreenCastStreamSrc *src = data;
|
||||||
MetaScreenCastStreamSrcPrivate *priv =
|
MetaScreenCastStreamSrcPrivate *priv =
|
||||||
meta_screen_cast_stream_src_get_instance_private (src);
|
meta_screen_cast_stream_src_get_instance_private (src);
|
||||||
uint32_t node_id;
|
|
||||||
|
|
||||||
switch (state)
|
switch (state)
|
||||||
{
|
{
|
||||||
@ -563,14 +546,12 @@ on_stream_state_changed (void *data,
|
|||||||
g_warning ("pipewire stream error: %s", error_message);
|
g_warning ("pipewire stream error: %s", error_message);
|
||||||
meta_screen_cast_stream_src_notify_closed (src);
|
meta_screen_cast_stream_src_notify_closed (src);
|
||||||
break;
|
break;
|
||||||
case PW_STREAM_STATE_CONFIGURE:
|
|
||||||
node_id = pw_stream_get_node_id (priv->pipewire_stream);
|
|
||||||
g_signal_emit (src, signals[READY], 0, (unsigned int) node_id);
|
|
||||||
break;
|
|
||||||
case PW_STREAM_STATE_UNCONNECTED:
|
|
||||||
case PW_STREAM_STATE_CONNECTING:
|
|
||||||
case PW_STREAM_STATE_READY:
|
|
||||||
case PW_STREAM_STATE_PAUSED:
|
case PW_STREAM_STATE_PAUSED:
|
||||||
|
if (priv->node_id == SPA_ID_INVALID && priv->pipewire_stream)
|
||||||
|
{
|
||||||
|
priv->node_id = pw_stream_get_node_id (priv->pipewire_stream);
|
||||||
|
g_signal_emit (src, signals[READY], 0, (unsigned int) priv->node_id);
|
||||||
|
}
|
||||||
if (meta_screen_cast_stream_src_is_enabled (src))
|
if (meta_screen_cast_stream_src_is_enabled (src))
|
||||||
meta_screen_cast_stream_src_disable (src);
|
meta_screen_cast_stream_src_disable (src);
|
||||||
break;
|
break;
|
||||||
@ -578,68 +559,69 @@ on_stream_state_changed (void *data,
|
|||||||
if (!meta_screen_cast_stream_src_is_enabled (src))
|
if (!meta_screen_cast_stream_src_is_enabled (src))
|
||||||
meta_screen_cast_stream_src_enable (src);
|
meta_screen_cast_stream_src_enable (src);
|
||||||
break;
|
break;
|
||||||
|
case PW_STREAM_STATE_UNCONNECTED:
|
||||||
|
case PW_STREAM_STATE_CONNECTING:
|
||||||
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
static void
|
static void
|
||||||
on_stream_format_changed (void *data,
|
on_stream_param_changed (void *data,
|
||||||
const struct spa_pod *format)
|
uint32_t id,
|
||||||
|
const struct spa_pod *format)
|
||||||
{
|
{
|
||||||
MetaScreenCastStreamSrc *src = data;
|
MetaScreenCastStreamSrc *src = data;
|
||||||
MetaScreenCastStreamSrcPrivate *priv =
|
MetaScreenCastStreamSrcPrivate *priv =
|
||||||
meta_screen_cast_stream_src_get_instance_private (src);
|
meta_screen_cast_stream_src_get_instance_private (src);
|
||||||
struct pw_type *pipewire_type = priv->pipewire_type;
|
|
||||||
uint8_t params_buffer[1024];
|
uint8_t params_buffer[1024];
|
||||||
int32_t width, height, stride, size;
|
int32_t width, height, stride, size;
|
||||||
struct spa_pod_builder pod_builder;
|
struct spa_pod_builder pod_builder;
|
||||||
const struct spa_pod *params[3];
|
const struct spa_pod *params[3];
|
||||||
const int bpp = 4;
|
const int bpp = 4;
|
||||||
|
|
||||||
if (!format)
|
if (!format || id != SPA_PARAM_Format)
|
||||||
{
|
return;
|
||||||
pw_stream_finish_format (priv->pipewire_stream, 0, NULL, 0);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
spa_format_video_raw_parse (format,
|
spa_format_video_raw_parse (format,
|
||||||
&priv->video_format,
|
&priv->video_format);
|
||||||
&priv->spa_type.format_video);
|
|
||||||
|
|
||||||
width = priv->video_format.size.width;
|
width = priv->video_format.size.width;
|
||||||
height = priv->video_format.size.height;
|
height = priv->video_format.size.height;
|
||||||
stride = SPA_ROUND_UP_N (width * bpp, 4);
|
stride = SPA_ROUND_UP_N (width * bpp, 4);
|
||||||
size = height * stride;
|
size = height * stride;
|
||||||
|
|
||||||
|
priv->video_stride = stride;
|
||||||
|
|
||||||
pod_builder = SPA_POD_BUILDER_INIT (params_buffer, sizeof (params_buffer));
|
pod_builder = SPA_POD_BUILDER_INIT (params_buffer, sizeof (params_buffer));
|
||||||
|
|
||||||
params[0] = spa_pod_builder_object (
|
params[0] = spa_pod_builder_add_object (
|
||||||
&pod_builder,
|
&pod_builder,
|
||||||
pipewire_type->param.idBuffers, pipewire_type->param_buffers.Buffers,
|
SPA_TYPE_OBJECT_ParamBuffers, SPA_PARAM_Buffers,
|
||||||
":", pipewire_type->param_buffers.size, "i", size,
|
SPA_PARAM_BUFFERS_buffers, SPA_POD_CHOICE_RANGE_Int (16, 2, 16),
|
||||||
":", pipewire_type->param_buffers.stride, "i", stride,
|
SPA_PARAM_BUFFERS_blocks, SPA_POD_Int (1),
|
||||||
":", pipewire_type->param_buffers.buffers, "iru", 16, PROP_RANGE (2, 16),
|
SPA_PARAM_BUFFERS_size, SPA_POD_Int (size),
|
||||||
":", pipewire_type->param_buffers.align, "i", 16);
|
SPA_PARAM_BUFFERS_stride, SPA_POD_Int (stride),
|
||||||
|
SPA_PARAM_BUFFERS_align, SPA_POD_Int (16));
|
||||||
|
|
||||||
params[1] = spa_pod_builder_object (
|
params[1] = spa_pod_builder_add_object (
|
||||||
&pod_builder,
|
&pod_builder,
|
||||||
pipewire_type->param.idMeta, pipewire_type->param_meta.Meta,
|
SPA_TYPE_OBJECT_ParamMeta, SPA_PARAM_Meta,
|
||||||
":", pipewire_type->param_meta.type, "I", pipewire_type->meta.VideoCrop,
|
SPA_PARAM_META_type, SPA_POD_Id (SPA_META_VideoCrop),
|
||||||
":", pipewire_type->param_meta.size, "i", sizeof (struct spa_meta_video_crop));
|
SPA_PARAM_META_size, SPA_POD_Int (sizeof (struct spa_meta_region)));
|
||||||
|
|
||||||
params[2] = spa_pod_builder_object (
|
params[2] = spa_pod_builder_add_object (
|
||||||
&pod_builder,
|
&pod_builder,
|
||||||
pipewire_type->param.idMeta, pipewire_type->param_meta.Meta,
|
SPA_TYPE_OBJECT_ParamMeta, SPA_PARAM_Meta,
|
||||||
":", pipewire_type->param_meta.type, "I", priv->spa_type.meta_cursor,
|
SPA_PARAM_META_type, SPA_POD_Id (SPA_META_Cursor),
|
||||||
":", pipewire_type->param_meta.size, "i", CURSOR_META_SIZE (64, 64));
|
SPA_PARAM_META_size, SPA_POD_Int (CURSOR_META_SIZE (64, 64)));
|
||||||
|
|
||||||
pw_stream_finish_format (priv->pipewire_stream, 0,
|
pw_stream_update_params (priv->pipewire_stream, params, G_N_ELEMENTS (params));
|
||||||
params, G_N_ELEMENTS (params));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static const struct pw_stream_events stream_events = {
|
static const struct pw_stream_events stream_events = {
|
||||||
PW_VERSION_STREAM_EVENTS,
|
PW_VERSION_STREAM_EVENTS,
|
||||||
.state_changed = on_stream_state_changed,
|
.state_changed = on_stream_state_changed,
|
||||||
.format_changed = on_stream_format_changed,
|
.param_changed = on_stream_param_changed,
|
||||||
};
|
};
|
||||||
|
|
||||||
static struct pw_stream *
|
static struct pw_stream *
|
||||||
@ -652,8 +634,6 @@ create_pipewire_stream (MetaScreenCastStreamSrc *src,
|
|||||||
uint8_t buffer[1024];
|
uint8_t buffer[1024];
|
||||||
struct spa_pod_builder pod_builder =
|
struct spa_pod_builder pod_builder =
|
||||||
SPA_POD_BUILDER_INIT (buffer, sizeof (buffer));
|
SPA_POD_BUILDER_INIT (buffer, sizeof (buffer));
|
||||||
MetaSpaType *spa_type = &priv->spa_type;
|
|
||||||
struct pw_type *pipewire_type = priv->pipewire_type;
|
|
||||||
float frame_rate;
|
float frame_rate;
|
||||||
MetaFraction frame_rate_fraction;
|
MetaFraction frame_rate_fraction;
|
||||||
struct spa_fraction max_framerate;
|
struct spa_fraction max_framerate;
|
||||||
@ -661,7 +641,9 @@ create_pipewire_stream (MetaScreenCastStreamSrc *src,
|
|||||||
const struct spa_pod *params[1];
|
const struct spa_pod *params[1];
|
||||||
int result;
|
int result;
|
||||||
|
|
||||||
pipewire_stream = pw_stream_new (priv->pipewire_remote,
|
priv->node_id = SPA_ID_INVALID;
|
||||||
|
|
||||||
|
pipewire_stream = pw_stream_new (priv->pipewire_core,
|
||||||
"meta-screen-cast-src",
|
"meta-screen-cast-src",
|
||||||
NULL);
|
NULL);
|
||||||
if (!pipewire_stream)
|
if (!pipewire_stream)
|
||||||
@ -682,17 +664,17 @@ create_pipewire_stream (MetaScreenCastStreamSrc *src,
|
|||||||
max_framerate = SPA_FRACTION (frame_rate_fraction.num,
|
max_framerate = SPA_FRACTION (frame_rate_fraction.num,
|
||||||
frame_rate_fraction.denom);
|
frame_rate_fraction.denom);
|
||||||
|
|
||||||
params[0] = spa_pod_builder_object (
|
params[0] = spa_pod_builder_add_object (
|
||||||
&pod_builder,
|
&pod_builder,
|
||||||
pipewire_type->param.idEnumFormat, pipewire_type->spa_format,
|
SPA_TYPE_OBJECT_Format, SPA_PARAM_EnumFormat,
|
||||||
"I", spa_type->media_type.video,
|
SPA_FORMAT_mediaType, SPA_POD_Id (SPA_MEDIA_TYPE_video),
|
||||||
"I", spa_type->media_subtype.raw,
|
SPA_FORMAT_mediaSubtype, SPA_POD_Id (SPA_MEDIA_SUBTYPE_raw),
|
||||||
":", spa_type->format_video.format, "I", spa_type->video_format.BGRx,
|
SPA_FORMAT_VIDEO_format, SPA_POD_Id (SPA_VIDEO_FORMAT_BGRx),
|
||||||
":", spa_type->format_video.size, "R", &SPA_RECTANGLE (priv->stream_width,
|
SPA_FORMAT_VIDEO_size, SPA_POD_Rectangle (&SPA_RECTANGLE (priv->stream_width,
|
||||||
priv->stream_height),
|
priv->stream_height)),
|
||||||
":", spa_type->format_video.framerate, "F", &SPA_FRACTION (0, 1),
|
SPA_FORMAT_VIDEO_framerate, SPA_POD_Fraction (&SPA_FRACTION (0, 1)),
|
||||||
":", spa_type->format_video.max_framerate, "Fru", &max_framerate,
|
SPA_FORMAT_VIDEO_maxFramerate, SPA_POD_CHOICE_RANGE_Fraction (&max_framerate,
|
||||||
PROP_RANGE (&min_framerate,
|
&min_framerate,
|
||||||
&max_framerate));
|
&max_framerate));
|
||||||
|
|
||||||
pw_stream_add_listener (pipewire_stream,
|
pw_stream_add_listener (pipewire_stream,
|
||||||
@ -702,7 +684,7 @@ create_pipewire_stream (MetaScreenCastStreamSrc *src,
|
|||||||
|
|
||||||
result = pw_stream_connect (pipewire_stream,
|
result = pw_stream_connect (pipewire_stream,
|
||||||
PW_DIRECTION_OUTPUT,
|
PW_DIRECTION_OUTPUT,
|
||||||
NULL,
|
SPA_ID_INVALID,
|
||||||
(PW_STREAM_FLAG_DRIVER |
|
(PW_STREAM_FLAG_DRIVER |
|
||||||
PW_STREAM_FLAG_MAP_BUFFERS),
|
PW_STREAM_FLAG_MAP_BUFFERS),
|
||||||
params, G_N_ELEMENTS (params));
|
params, G_N_ELEMENTS (params));
|
||||||
@ -717,40 +699,18 @@ create_pipewire_stream (MetaScreenCastStreamSrc *src,
|
|||||||
}
|
}
|
||||||
|
|
||||||
static void
|
static void
|
||||||
on_state_changed (void *data,
|
on_core_error (void *data,
|
||||||
enum pw_remote_state old,
|
uint32_t id,
|
||||||
enum pw_remote_state state,
|
int seq,
|
||||||
const char *error_message)
|
int res,
|
||||||
|
const char *message)
|
||||||
{
|
{
|
||||||
MetaScreenCastStreamSrc *src = data;
|
MetaScreenCastStreamSrc *src = data;
|
||||||
MetaScreenCastStreamSrcPrivate *priv =
|
|
||||||
meta_screen_cast_stream_src_get_instance_private (src);
|
|
||||||
struct pw_stream *pipewire_stream;
|
|
||||||
GError *error = NULL;
|
|
||||||
|
|
||||||
switch (state)
|
g_warning ("pipewire remote error: id:%u %s", id, message);
|
||||||
{
|
|
||||||
case PW_REMOTE_STATE_ERROR:
|
if (id == PW_ID_CORE && res == -EPIPE)
|
||||||
g_warning ("pipewire remote error: %s\n", error_message);
|
meta_screen_cast_stream_src_notify_closed (src);
|
||||||
meta_screen_cast_stream_src_notify_closed (src);
|
|
||||||
break;
|
|
||||||
case PW_REMOTE_STATE_CONNECTED:
|
|
||||||
pipewire_stream = create_pipewire_stream (src, &error);
|
|
||||||
if (!pipewire_stream)
|
|
||||||
{
|
|
||||||
g_warning ("Could not create pipewire stream: %s", error->message);
|
|
||||||
g_error_free (error);
|
|
||||||
meta_screen_cast_stream_src_notify_closed (src);
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
priv->pipewire_stream = pipewire_stream;
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
case PW_REMOTE_STATE_UNCONNECTED:
|
|
||||||
case PW_REMOTE_STATE_CONNECTING:
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static gboolean
|
static gboolean
|
||||||
@ -793,17 +753,6 @@ static GSourceFuncs pipewire_source_funcs =
|
|||||||
pipewire_loop_source_finalize
|
pipewire_loop_source_finalize
|
||||||
};
|
};
|
||||||
|
|
||||||
static void
|
|
||||||
init_spa_type (MetaSpaType *type,
|
|
||||||
struct spa_type_map *map)
|
|
||||||
{
|
|
||||||
spa_type_media_type_map (map, &type->media_type);
|
|
||||||
spa_type_media_subtype_map (map, &type->media_subtype);
|
|
||||||
spa_type_format_video_map (map, &type->format_video);
|
|
||||||
spa_type_video_format_map (map, &type->video_format);
|
|
||||||
type->meta_cursor = spa_type_map_get_id(map, SPA_TYPE_META__Cursor);
|
|
||||||
}
|
|
||||||
|
|
||||||
static MetaPipeWireSource *
|
static MetaPipeWireSource *
|
||||||
create_pipewire_source (void)
|
create_pipewire_source (void)
|
||||||
{
|
{
|
||||||
@ -829,9 +778,9 @@ create_pipewire_source (void)
|
|||||||
return pipewire_source;
|
return pipewire_source;
|
||||||
}
|
}
|
||||||
|
|
||||||
static const struct pw_remote_events remote_events = {
|
static const struct pw_core_events core_events = {
|
||||||
PW_VERSION_REMOTE_EVENTS,
|
PW_VERSION_CORE_EVENTS,
|
||||||
.state_changed = on_state_changed,
|
.error = on_core_error,
|
||||||
};
|
};
|
||||||
|
|
||||||
static gboolean
|
static gboolean
|
||||||
@ -851,37 +800,31 @@ meta_screen_cast_stream_src_initable_init (GInitable *initable,
|
|||||||
return FALSE;
|
return FALSE;
|
||||||
}
|
}
|
||||||
|
|
||||||
priv->pipewire_core = pw_core_new (priv->pipewire_source->pipewire_loop,
|
priv->pipewire_context = pw_context_new (priv->pipewire_source->pipewire_loop,
|
||||||
NULL);
|
NULL, 0);
|
||||||
|
if (!priv->pipewire_context)
|
||||||
|
{
|
||||||
|
g_set_error (error, G_IO_ERROR, G_IO_ERROR_FAILED,
|
||||||
|
"Failed to create pipewire context");
|
||||||
|
return FALSE;
|
||||||
|
}
|
||||||
|
|
||||||
|
priv->pipewire_core = pw_context_connect (priv->pipewire_context, NULL, 0);
|
||||||
if (!priv->pipewire_core)
|
if (!priv->pipewire_core)
|
||||||
{
|
{
|
||||||
g_set_error (error, G_IO_ERROR, G_IO_ERROR_FAILED,
|
g_set_error (error, G_IO_ERROR, G_IO_ERROR_FAILED,
|
||||||
"Failed to create pipewire core");
|
"Couldn't connect pipewire context");
|
||||||
return FALSE;
|
return FALSE;
|
||||||
}
|
}
|
||||||
|
|
||||||
priv->pipewire_remote = pw_remote_new (priv->pipewire_core, NULL, 0);
|
pw_core_add_listener (priv->pipewire_core,
|
||||||
if (!priv->pipewire_remote)
|
&priv->pipewire_core_listener,
|
||||||
{
|
&core_events,
|
||||||
g_set_error (error, G_IO_ERROR, G_IO_ERROR_FAILED,
|
src);
|
||||||
"Couldn't creat pipewire remote");
|
|
||||||
return FALSE;
|
|
||||||
}
|
|
||||||
|
|
||||||
pw_remote_add_listener (priv->pipewire_remote,
|
priv->pipewire_stream = create_pipewire_stream (src, error);
|
||||||
&priv->pipewire_remote_listener,
|
if (!priv->pipewire_stream)
|
||||||
&remote_events,
|
return FALSE;
|
||||||
src);
|
|
||||||
|
|
||||||
priv->pipewire_type = pw_core_get_type (priv->pipewire_core);
|
|
||||||
init_spa_type (&priv->spa_type, priv->pipewire_type->map);
|
|
||||||
|
|
||||||
if (pw_remote_connect (priv->pipewire_remote) != 0)
|
|
||||||
{
|
|
||||||
g_set_error (error, G_IO_ERROR, G_IO_ERROR_FAILED,
|
|
||||||
"Couldn't connect pipewire remote");
|
|
||||||
return FALSE;
|
|
||||||
}
|
|
||||||
|
|
||||||
return TRUE;
|
return TRUE;
|
||||||
}
|
}
|
||||||
@ -912,8 +855,8 @@ meta_screen_cast_stream_src_finalize (GObject *object)
|
|||||||
meta_screen_cast_stream_src_disable (src);
|
meta_screen_cast_stream_src_disable (src);
|
||||||
|
|
||||||
g_clear_pointer (&priv->pipewire_stream, pw_stream_destroy);
|
g_clear_pointer (&priv->pipewire_stream, pw_stream_destroy);
|
||||||
g_clear_pointer (&priv->pipewire_remote, pw_remote_destroy);
|
g_clear_pointer (&priv->pipewire_core, pw_core_disconnect);
|
||||||
g_clear_pointer (&priv->pipewire_core, pw_core_destroy);
|
g_clear_pointer (&priv->pipewire_context, pw_context_destroy);
|
||||||
g_source_destroy (&priv->pipewire_source->base);
|
g_source_destroy (&priv->pipewire_source->base);
|
||||||
|
|
||||||
G_OBJECT_CLASS (meta_screen_cast_stream_src_parent_class)->finalize (object);
|
G_OBJECT_CLASS (meta_screen_cast_stream_src_parent_class)->finalize (object);
|
||||||
|
Loading…
Reference in New Issue
Block a user