mirror of
https://github.com/brl/mutter.git
synced 2024-12-26 04:42:14 +00:00
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;
|
||||
|
||||
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
|
||||
|
@ -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
|
||||
|
@ -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;
|
||||
|
||||
@ -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
|
||||
on_stream_param_changed (void *data,
|
||||
uint32_t id,
|
||||
@ -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);
|
||||
|
@ -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);
|
||||
|
||||
|
@ -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
|
||||
|
@ -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
|
||||
|
Loading…
Reference in New Issue
Block a user