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>
This commit is contained in:
parent
6223742996
commit
776e3f329d
@ -169,7 +169,7 @@ sync_cursor_state (MetaScreenCastAreaStreamSrc *area_src)
|
|||||||
return;
|
return;
|
||||||
|
|
||||||
flags = META_SCREEN_CAST_RECORD_FLAG_CURSOR_ONLY;
|
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
|
static void
|
||||||
@ -239,7 +239,7 @@ maybe_record_frame_on_idle (gpointer user_data)
|
|||||||
area_src->maybe_record_idle_id = 0;
|
area_src->maybe_record_idle_id = 0;
|
||||||
|
|
||||||
flags = META_SCREEN_CAST_RECORD_FLAG_NONE;
|
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;
|
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);
|
g_clear_handle_id (&area_src->maybe_record_idle_id, g_source_remove);
|
||||||
|
|
||||||
flags = META_SCREEN_CAST_RECORD_FLAG_NONE;
|
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
|
static void
|
||||||
|
@ -143,7 +143,7 @@ maybe_record_frame_on_idle (gpointer user_data)
|
|||||||
monitor_src->maybe_record_idle_id = 0;
|
monitor_src->maybe_record_idle_id = 0;
|
||||||
|
|
||||||
flags = META_SCREEN_CAST_RECORD_FLAG_NONE;
|
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;
|
return G_SOURCE_REMOVE;
|
||||||
}
|
}
|
||||||
@ -185,7 +185,7 @@ before_stage_painted (MetaStage *stage,
|
|||||||
return;
|
return;
|
||||||
|
|
||||||
flags = META_SCREEN_CAST_RECORD_FLAG_DMABUF_ONLY;
|
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
|
static gboolean
|
||||||
@ -264,7 +264,7 @@ sync_cursor_state (MetaScreenCastMonitorStreamSrc *monitor_src)
|
|||||||
return;
|
return;
|
||||||
|
|
||||||
flags = META_SCREEN_CAST_RECORD_FLAG_CURSOR_ONLY;
|
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
|
static void
|
||||||
|
@ -51,6 +51,7 @@
|
|||||||
(sizeof (struct spa_meta_cursor) + \
|
(sizeof (struct spa_meta_cursor) + \
|
||||||
sizeof (struct spa_meta_bitmap) + width * height * 4)
|
sizeof (struct spa_meta_bitmap) + width * height * 4)
|
||||||
|
|
||||||
|
#define NUM_DAMAGED_RECTS 32
|
||||||
#define DEFAULT_SIZE SPA_RECTANGLE (1280, 720)
|
#define DEFAULT_SIZE SPA_RECTANGLE (1280, 720)
|
||||||
#define MIN_SIZE SPA_RECTANGLE (1, 1)
|
#define MIN_SIZE SPA_RECTANGLE (1, 1)
|
||||||
#define MAX_SIZE SPA_RECTANGLE (16384, 16386)
|
#define MAX_SIZE SPA_RECTANGLE (16384, 16386)
|
||||||
@ -107,6 +108,8 @@ typedef struct _MetaScreenCastStreamSrcPrivate
|
|||||||
guint follow_up_frame_source_id;
|
guint follow_up_frame_source_id;
|
||||||
|
|
||||||
GHashTable *dmabuf_handles;
|
GHashTable *dmabuf_handles;
|
||||||
|
|
||||||
|
cairo_region_t *redraw_clip;
|
||||||
} MetaScreenCastStreamSrcPrivate;
|
} MetaScreenCastStreamSrcPrivate;
|
||||||
|
|
||||||
static struct spa_pod *
|
static struct spa_pod *
|
||||||
@ -602,9 +605,81 @@ meta_screen_cast_stream_src_calculate_stride (MetaScreenCastStreamSrc *src,
|
|||||||
return priv->video_stride;
|
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
|
void
|
||||||
meta_screen_cast_stream_src_maybe_record_frame (MetaScreenCastStreamSrc *src,
|
meta_screen_cast_stream_src_maybe_record_frame (MetaScreenCastStreamSrc *src,
|
||||||
MetaScreenCastRecordFlag flags)
|
MetaScreenCastRecordFlag flags,
|
||||||
|
const cairo_region_t *redraw_clip)
|
||||||
{
|
{
|
||||||
MetaScreenCastStreamSrcPrivate *priv =
|
MetaScreenCastStreamSrcPrivate *priv =
|
||||||
meta_screen_cast_stream_src_get_instance_private (src);
|
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;
|
uint64_t now_us;
|
||||||
g_autoptr (GError) error = NULL;
|
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 ();
|
now_us = g_get_monotonic_time ();
|
||||||
if (priv->video_format.max_framerate.num > 0 &&
|
if (priv->video_format.max_framerate.num > 0 &&
|
||||||
priv->last_frame_timestamp_us != 0)
|
priv->last_frame_timestamp_us != 0)
|
||||||
@ -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);
|
g_clear_handle_id (&priv->follow_up_frame_source_id, g_source_remove);
|
||||||
if (do_record_frame (src, flags, spa_buffer, data, &error))
|
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_data *spa_data = &spa_buffer->datas[0];
|
||||||
struct spa_meta_region *spa_meta_video_crop;
|
struct spa_meta_region *spa_meta_video_crop;
|
||||||
|
|
||||||
@ -823,6 +910,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
|
static void
|
||||||
on_stream_param_changed (void *data,
|
on_stream_param_changed (void *data,
|
||||||
uint32_t id,
|
uint32_t id,
|
||||||
@ -836,7 +940,7 @@ on_stream_param_changed (void *data,
|
|||||||
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[4];
|
const struct spa_pod *params[5];
|
||||||
int n_params = 0;
|
int n_params = 0;
|
||||||
const int bpp = 4;
|
const int bpp = 4;
|
||||||
int buffer_types;
|
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_type, SPA_POD_Id (SPA_META_Header),
|
||||||
SPA_PARAM_META_size, SPA_POD_Int (sizeof (struct 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)
|
if (klass->notify_params_updated)
|
||||||
klass->notify_params_updated (src, &priv->video_format);
|
klass->notify_params_updated (src, &priv->video_format);
|
||||||
|
@ -85,7 +85,8 @@ void meta_screen_cast_stream_src_close (MetaScreenCastStreamSrc *src);
|
|||||||
gboolean meta_screen_cast_stream_src_is_enabled (MetaScreenCastStreamSrc *src);
|
gboolean meta_screen_cast_stream_src_is_enabled (MetaScreenCastStreamSrc *src);
|
||||||
|
|
||||||
void meta_screen_cast_stream_src_maybe_record_frame (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);
|
gboolean meta_screen_cast_stream_src_pending_follow_up_frame (MetaScreenCastStreamSrc *src);
|
||||||
|
|
||||||
|
@ -123,7 +123,7 @@ sync_cursor_state (MetaScreenCastVirtualStreamSrc *virtual_src)
|
|||||||
return;
|
return;
|
||||||
|
|
||||||
flags = META_SCREEN_CAST_RECORD_FLAG_CURSOR_ONLY;
|
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
|
static void
|
||||||
@ -190,9 +190,11 @@ actors_painted (MetaStage *stage,
|
|||||||
{
|
{
|
||||||
MetaScreenCastStreamSrc *src = META_SCREEN_CAST_STREAM_SRC (user_data);
|
MetaScreenCastStreamSrc *src = META_SCREEN_CAST_STREAM_SRC (user_data);
|
||||||
MetaScreenCastRecordFlag flags;
|
MetaScreenCastRecordFlag flags;
|
||||||
|
const cairo_region_t *redraw_clip = NULL;
|
||||||
|
|
||||||
flags = META_SCREEN_CAST_RECORD_FLAG_NONE;
|
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
|
static void
|
||||||
|
@ -373,7 +373,7 @@ screen_cast_window_damaged (MetaWindowActor *actor,
|
|||||||
MetaScreenCastRecordFlag flags;
|
MetaScreenCastRecordFlag flags;
|
||||||
|
|
||||||
flags = META_SCREEN_CAST_RECORD_FLAG_NONE;
|
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
|
static void
|
||||||
@ -394,7 +394,7 @@ sync_cursor_state (MetaScreenCastWindowStreamSrc *window_src)
|
|||||||
return;
|
return;
|
||||||
|
|
||||||
flags = META_SCREEN_CAST_RECORD_FLAG_CURSOR_ONLY;
|
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
|
static void
|
||||||
@ -477,7 +477,7 @@ meta_screen_cast_window_stream_src_enable (MetaScreenCastStreamSrc *src)
|
|||||||
}
|
}
|
||||||
|
|
||||||
flags = META_SCREEN_CAST_RECORD_FLAG_NONE;
|
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
|
static void
|
||||||
@ -551,7 +551,7 @@ meta_screen_cast_window_stream_record_follow_up (MetaScreenCastStreamSrc *src)
|
|||||||
MetaScreenCastRecordFlag flags;
|
MetaScreenCastRecordFlag flags;
|
||||||
|
|
||||||
flags = META_SCREEN_CAST_RECORD_FLAG_NONE;
|
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
|
static void
|
||||||
|
Loading…
Reference in New Issue
Block a user