summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorSalman <salmanmalik@chromium.org>2023-02-03 19:33:57 +0000
committerMarge Bot <marge-bot@gnome.org>2023-04-06 23:09:43 +0000
commit776e3f329d747e3ac8cd23935e558bedda629846 (patch)
tree611d5771b7c854a9cec717a5bb528d74eba22dd2
parent62237429960fe213265d73ba052b4e94d102ed68 (diff)
downloadmutter-776e3f329d747e3ac8cd23935e558bedda629846.tar.gz
screen-cast-stream-src: Export damaged video regions
This change will export the damaged regions (when available) out to the pipewire client. This change is currently specific to virtual streams only (where I was able to test the change) and maintains the current behavior for other screencast stream types. Part-of: <https://gitlab.gnome.org/GNOME/mutter/-/merge_requests/2775>
-rw-r--r--src/backends/meta-screen-cast-area-stream-src.c6
-rw-r--r--src/backends/meta-screen-cast-monitor-stream-src.c6
-rw-r--r--src/backends/meta-screen-cast-stream-src.c114
-rw-r--r--src/backends/meta-screen-cast-stream-src.h3
-rw-r--r--src/backends/meta-screen-cast-virtual-stream-src.c6
-rw-r--r--src/backends/meta-screen-cast-window-stream-src.c8
6 files changed, 126 insertions, 17 deletions
diff --git a/src/backends/meta-screen-cast-area-stream-src.c b/src/backends/meta-screen-cast-area-stream-src.c
index 0d2887a1b..c0b6b39c0 100644
--- a/src/backends/meta-screen-cast-area-stream-src.c
+++ b/src/backends/meta-screen-cast-area-stream-src.c
@@ -169,7 +169,7 @@ sync_cursor_state (MetaScreenCastAreaStreamSrc *area_src)
return;
flags = META_SCREEN_CAST_RECORD_FLAG_CURSOR_ONLY;
- meta_screen_cast_stream_src_maybe_record_frame (src, flags);
+ meta_screen_cast_stream_src_maybe_record_frame (src, flags, NULL);
}
static void
@@ -239,7 +239,7 @@ maybe_record_frame_on_idle (gpointer user_data)
area_src->maybe_record_idle_id = 0;
flags = META_SCREEN_CAST_RECORD_FLAG_NONE;
- meta_screen_cast_stream_src_maybe_record_frame (src, flags);
+ meta_screen_cast_stream_src_maybe_record_frame (src, flags, NULL);
return G_SOURCE_REMOVE;
}
@@ -544,7 +544,7 @@ meta_screen_cast_area_stream_record_follow_up (MetaScreenCastStreamSrc *src)
g_clear_handle_id (&area_src->maybe_record_idle_id, g_source_remove);
flags = META_SCREEN_CAST_RECORD_FLAG_NONE;
- meta_screen_cast_stream_src_maybe_record_frame (src, flags);
+ meta_screen_cast_stream_src_maybe_record_frame (src, flags, NULL);
}
static void
diff --git a/src/backends/meta-screen-cast-monitor-stream-src.c b/src/backends/meta-screen-cast-monitor-stream-src.c
index 8a63bc994..5ed744f56 100644
--- a/src/backends/meta-screen-cast-monitor-stream-src.c
+++ b/src/backends/meta-screen-cast-monitor-stream-src.c
@@ -143,7 +143,7 @@ maybe_record_frame_on_idle (gpointer user_data)
monitor_src->maybe_record_idle_id = 0;
flags = META_SCREEN_CAST_RECORD_FLAG_NONE;
- meta_screen_cast_stream_src_maybe_record_frame (src, flags);
+ meta_screen_cast_stream_src_maybe_record_frame (src, flags, NULL);
return G_SOURCE_REMOVE;
}
@@ -185,7 +185,7 @@ before_stage_painted (MetaStage *stage,
return;
flags = META_SCREEN_CAST_RECORD_FLAG_DMABUF_ONLY;
- meta_screen_cast_stream_src_maybe_record_frame (src, flags);
+ meta_screen_cast_stream_src_maybe_record_frame (src, flags, NULL);
}
static gboolean
@@ -264,7 +264,7 @@ sync_cursor_state (MetaScreenCastMonitorStreamSrc *monitor_src)
return;
flags = META_SCREEN_CAST_RECORD_FLAG_CURSOR_ONLY;
- meta_screen_cast_stream_src_maybe_record_frame (src, flags);
+ meta_screen_cast_stream_src_maybe_record_frame (src, flags, NULL);
}
static void
diff --git a/src/backends/meta-screen-cast-stream-src.c b/src/backends/meta-screen-cast-stream-src.c
index e3d56d16b..c757bbd28 100644
--- a/src/backends/meta-screen-cast-stream-src.c
+++ b/src/backends/meta-screen-cast-stream-src.c
@@ -51,6 +51,7 @@
(sizeof (struct spa_meta_cursor) + \
sizeof (struct spa_meta_bitmap) + width * height * 4)
+#define NUM_DAMAGED_RECTS 32
#define DEFAULT_SIZE SPA_RECTANGLE (1280, 720)
#define MIN_SIZE SPA_RECTANGLE (1, 1)
#define MAX_SIZE SPA_RECTANGLE (16384, 16386)
@@ -107,6 +108,8 @@ typedef struct _MetaScreenCastStreamSrcPrivate
guint follow_up_frame_source_id;
GHashTable *dmabuf_handles;
+
+ cairo_region_t *redraw_clip;
} MetaScreenCastStreamSrcPrivate;
static struct spa_pod *
@@ -602,9 +605,81 @@ meta_screen_cast_stream_src_calculate_stride (MetaScreenCastStreamSrc *src,
return priv->video_stride;
}
+static void
+maybe_add_damaged_regions_metadata (MetaScreenCastStreamSrc *src,
+ struct spa_buffer *spa_buffer)
+{
+ MetaScreenCastStreamSrcPrivate *priv;
+ struct spa_meta *spa_meta_video_damage;
+ struct spa_meta_region *meta_region;
+
+ spa_meta_video_damage =
+ spa_buffer_find_meta (spa_buffer, SPA_META_VideoDamage);
+ if (!spa_meta_video_damage)
+ return;
+
+ priv = meta_screen_cast_stream_src_get_instance_private (src);
+ if (!priv->redraw_clip)
+ {
+ spa_meta_for_each (meta_region, spa_meta_video_damage)
+ {
+ meta_region->region = SPA_REGION (0, 0, priv->video_format.size.width,
+ priv->video_format.size.height);
+ break;
+ }
+ }
+ else
+ {
+ int i;
+ int n_rectangles;
+ int num_buffers_available;
+
+ i = 0;
+ n_rectangles = cairo_region_num_rectangles (priv->redraw_clip);
+ num_buffers_available = 0;
+
+ spa_meta_for_each (meta_region, spa_meta_video_damage)
+ {
+ ++num_buffers_available;
+ }
+
+ if (num_buffers_available < n_rectangles)
+ {
+ spa_meta_for_each (meta_region, spa_meta_video_damage)
+ {
+ g_warning ("Not enough buffers (%d) to accomodate damaged "
+ "regions (%d)", num_buffers_available, n_rectangles);
+ meta_region->region = SPA_REGION (0, 0,
+ priv->video_format.size.width,
+ priv->video_format.size.height);
+
+ break;
+ }
+ }
+ else
+ {
+ spa_meta_for_each (meta_region, spa_meta_video_damage)
+ {
+ cairo_rectangle_int_t rect;
+
+ cairo_region_get_rectangle (priv->redraw_clip, i, &rect);
+ meta_region->region = SPA_REGION (rect.x, rect.y,
+ rect.width, rect.height);
+
+ if (++i == n_rectangles)
+ break;
+ }
+ }
+ }
+
+ g_clear_pointer (&priv->redraw_clip, cairo_region_destroy);
+}
+
+
void
meta_screen_cast_stream_src_maybe_record_frame (MetaScreenCastStreamSrc *src,
- MetaScreenCastRecordFlag flags)
+ MetaScreenCastRecordFlag flags,
+ const cairo_region_t *redraw_clip)
{
MetaScreenCastStreamSrcPrivate *priv =
meta_screen_cast_stream_src_get_instance_private (src);
@@ -616,6 +691,17 @@ meta_screen_cast_stream_src_maybe_record_frame (MetaScreenCastStreamSrc *src,
uint64_t now_us;
g_autoptr (GError) error = NULL;
+ /* Accumulate the damaged region since we might not schedule a frame capture
+ * eventually but once we do, we should report all the previous damaged areas.
+ */
+ if (redraw_clip)
+ {
+ if (priv->redraw_clip)
+ cairo_region_union (priv->redraw_clip, redraw_clip);
+ else
+ priv->redraw_clip = cairo_region_copy (redraw_clip);
+ }
+
now_us = g_get_monotonic_time ();
if (priv->video_format.max_framerate.num > 0 &&
priv->last_frame_timestamp_us != 0)
@@ -646,7 +732,7 @@ meta_screen_cast_stream_src_maybe_record_frame (MetaScreenCastStreamSrc *src,
meta_topic (META_DEBUG_SCREEN_CAST, "Recording %s frame on stream %u",
flags & META_SCREEN_CAST_RECORD_FLAG_CURSOR_ONLY ?
- "cursor" : "full",
+ "cursor" : "full",
priv->node_id);
buffer = pw_stream_dequeue_buffer (priv->pipewire_stream);
@@ -681,6 +767,7 @@ meta_screen_cast_stream_src_maybe_record_frame (MetaScreenCastStreamSrc *src,
g_clear_handle_id (&priv->follow_up_frame_source_id, g_source_remove);
if (do_record_frame (src, flags, spa_buffer, data, &error))
{
+ maybe_add_damaged_regions_metadata (src, spa_buffer);
struct spa_data *spa_data = &spa_buffer->datas[0];
struct spa_meta_region *spa_meta_video_crop;
@@ -824,6 +911,23 @@ on_stream_state_changed (void *data,
}
static void
+add_video_damage_meta_param (struct spa_pod_builder *pod_builder,
+ const struct spa_pod **params,
+ int idx)
+{
+ const size_t meta_region_size = sizeof (struct spa_meta_region);
+
+ params[idx] = spa_pod_builder_add_object (
+ pod_builder,
+ SPA_TYPE_OBJECT_ParamMeta, SPA_PARAM_Meta,
+ SPA_PARAM_META_type, SPA_POD_Id (SPA_META_VideoDamage),
+ SPA_PARAM_META_size,
+ SPA_POD_CHOICE_RANGE_Int (meta_region_size * NUM_DAMAGED_RECTS,
+ meta_region_size * 1,
+ meta_region_size * NUM_DAMAGED_RECTS));
+}
+
+static void
on_stream_param_changed (void *data,
uint32_t id,
const struct spa_pod *format)
@@ -836,7 +940,7 @@ on_stream_param_changed (void *data,
uint8_t params_buffer[1024];
int32_t width, height, stride, size;
struct spa_pod_builder pod_builder;
- const struct spa_pod *params[4];
+ const struct spa_pod *params[5];
int n_params = 0;
const int bpp = 4;
int buffer_types;
@@ -888,7 +992,9 @@ on_stream_param_changed (void *data,
SPA_PARAM_META_type, SPA_POD_Id (SPA_META_Header),
SPA_PARAM_META_size, SPA_POD_Int (sizeof (struct spa_meta_header)));
- pw_stream_update_params (priv->pipewire_stream, params, G_N_ELEMENTS (params));
+ add_video_damage_meta_param (&pod_builder, params, n_params++);
+
+ pw_stream_update_params (priv->pipewire_stream, params, n_params);
if (klass->notify_params_updated)
klass->notify_params_updated (src, &priv->video_format);
diff --git a/src/backends/meta-screen-cast-stream-src.h b/src/backends/meta-screen-cast-stream-src.h
index 03b05c144..65952cc49 100644
--- a/src/backends/meta-screen-cast-stream-src.h
+++ b/src/backends/meta-screen-cast-stream-src.h
@@ -85,7 +85,8 @@ void meta_screen_cast_stream_src_close (MetaScreenCastStreamSrc *src);
gboolean meta_screen_cast_stream_src_is_enabled (MetaScreenCastStreamSrc *src);
void meta_screen_cast_stream_src_maybe_record_frame (MetaScreenCastStreamSrc *src,
- MetaScreenCastRecordFlag flags);
+ MetaScreenCastRecordFlag flags,
+ const cairo_region_t *redraw_clip);
gboolean meta_screen_cast_stream_src_pending_follow_up_frame (MetaScreenCastStreamSrc *src);
diff --git a/src/backends/meta-screen-cast-virtual-stream-src.c b/src/backends/meta-screen-cast-virtual-stream-src.c
index 34dc2d179..9cb8e98f5 100644
--- a/src/backends/meta-screen-cast-virtual-stream-src.c
+++ b/src/backends/meta-screen-cast-virtual-stream-src.c
@@ -123,7 +123,7 @@ sync_cursor_state (MetaScreenCastVirtualStreamSrc *virtual_src)
return;
flags = META_SCREEN_CAST_RECORD_FLAG_CURSOR_ONLY;
- meta_screen_cast_stream_src_maybe_record_frame (src, flags);
+ meta_screen_cast_stream_src_maybe_record_frame (src, flags, NULL);
}
static void
@@ -190,9 +190,11 @@ actors_painted (MetaStage *stage,
{
MetaScreenCastStreamSrc *src = META_SCREEN_CAST_STREAM_SRC (user_data);
MetaScreenCastRecordFlag flags;
+ const cairo_region_t *redraw_clip = NULL;
flags = META_SCREEN_CAST_RECORD_FLAG_NONE;
- meta_screen_cast_stream_src_maybe_record_frame (src, flags);
+ redraw_clip = clutter_paint_context_get_redraw_clip (paint_context);
+ meta_screen_cast_stream_src_maybe_record_frame (src, flags, redraw_clip);
}
static void
diff --git a/src/backends/meta-screen-cast-window-stream-src.c b/src/backends/meta-screen-cast-window-stream-src.c
index 67251bf36..fca0b214c 100644
--- a/src/backends/meta-screen-cast-window-stream-src.c
+++ b/src/backends/meta-screen-cast-window-stream-src.c
@@ -373,7 +373,7 @@ screen_cast_window_damaged (MetaWindowActor *actor,
MetaScreenCastRecordFlag flags;
flags = META_SCREEN_CAST_RECORD_FLAG_NONE;
- meta_screen_cast_stream_src_maybe_record_frame (src, flags);
+ meta_screen_cast_stream_src_maybe_record_frame (src, flags, NULL);
}
static void
@@ -394,7 +394,7 @@ sync_cursor_state (MetaScreenCastWindowStreamSrc *window_src)
return;
flags = META_SCREEN_CAST_RECORD_FLAG_CURSOR_ONLY;
- meta_screen_cast_stream_src_maybe_record_frame (src, flags);
+ meta_screen_cast_stream_src_maybe_record_frame (src, flags, NULL);
}
static void
@@ -477,7 +477,7 @@ meta_screen_cast_window_stream_src_enable (MetaScreenCastStreamSrc *src)
}
flags = META_SCREEN_CAST_RECORD_FLAG_NONE;
- meta_screen_cast_stream_src_maybe_record_frame (src, flags);
+ meta_screen_cast_stream_src_maybe_record_frame (src, flags, NULL);
}
static void
@@ -551,7 +551,7 @@ meta_screen_cast_window_stream_record_follow_up (MetaScreenCastStreamSrc *src)
MetaScreenCastRecordFlag flags;
flags = META_SCREEN_CAST_RECORD_FLAG_NONE;
- meta_screen_cast_stream_src_maybe_record_frame (src, flags);
+ meta_screen_cast_stream_src_maybe_record_frame (src, flags, NULL);
}
static void