shell-recorder: Use clutter-computed sizes and scaling for the capture
Get from clutter the capture sizes and scale and don't mind about doing any rounding here, as it might be different from the one done at clutter level (causing mismatch and not-working videos). Delegate this to clutter, and forget about the internal details. These values are then used to composte the image and set the video caps. https://bugzilla.gnome.org/show_bug.cgi?id=7650111
This commit is contained in:
parent
4a4f752459
commit
6d6c2e5b99
@ -51,6 +51,10 @@ struct _ShellRecorder {
|
|||||||
int stage_width;
|
int stage_width;
|
||||||
int stage_height;
|
int stage_height;
|
||||||
|
|
||||||
|
int capture_width;
|
||||||
|
int capture_height;
|
||||||
|
float scale;
|
||||||
|
|
||||||
int pointer_x;
|
int pointer_x;
|
||||||
int pointer_y;
|
int pointer_y;
|
||||||
|
|
||||||
@ -430,10 +434,8 @@ recorder_record_frame (ShellRecorder *recorder,
|
|||||||
return;
|
return;
|
||||||
recorder->last_frame_time = now;
|
recorder->last_frame_time = now;
|
||||||
|
|
||||||
clutter_stage_capture (recorder->stage, paint, &recorder->area,
|
if (!clutter_stage_capture (recorder->stage, paint, &recorder->area,
|
||||||
&captures, &n_captures);
|
&captures, &n_captures))
|
||||||
|
|
||||||
if (n_captures == 0)
|
|
||||||
return;
|
return;
|
||||||
|
|
||||||
if (n_captures == 1)
|
if (n_captures == 1)
|
||||||
@ -443,8 +445,9 @@ recorder_record_frame (ShellRecorder *recorder,
|
|||||||
n_captures,
|
n_captures,
|
||||||
recorder->area.x,
|
recorder->area.x,
|
||||||
recorder->area.y,
|
recorder->area.y,
|
||||||
recorder->area.width,
|
recorder->capture_width,
|
||||||
recorder->area.height);
|
recorder->capture_height,
|
||||||
|
recorder->scale);
|
||||||
|
|
||||||
data = cairo_image_surface_get_data (image);
|
data = cairo_image_surface_get_data (image);
|
||||||
size = (cairo_image_surface_get_height (image) *
|
size = (cairo_image_surface_get_height (image) *
|
||||||
@ -500,6 +503,11 @@ recorder_update_size (ShellRecorder *recorder)
|
|||||||
recorder->area.y = 0;
|
recorder->area.y = 0;
|
||||||
recorder->area.width = recorder->stage_width;
|
recorder->area.width = recorder->stage_width;
|
||||||
recorder->area.height = recorder->stage_height;
|
recorder->area.height = recorder->stage_height;
|
||||||
|
|
||||||
|
clutter_stage_get_capture_final_size (recorder->stage, NULL,
|
||||||
|
&recorder->capture_width,
|
||||||
|
&recorder->capture_height,
|
||||||
|
&recorder->scale);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -618,6 +626,8 @@ recorder_connect_stage_callbacks (ShellRecorder *recorder)
|
|||||||
G_CALLBACK (recorder_on_stage_notify_size), recorder);
|
G_CALLBACK (recorder_on_stage_notify_size), recorder);
|
||||||
g_signal_connect (recorder->stage, "notify::height",
|
g_signal_connect (recorder->stage, "notify::height",
|
||||||
G_CALLBACK (recorder_on_stage_notify_size), recorder);
|
G_CALLBACK (recorder_on_stage_notify_size), recorder);
|
||||||
|
g_signal_connect (recorder->stage, "notify::resource-scale",
|
||||||
|
G_CALLBACK (recorder_on_stage_notify_size), recorder);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void
|
static void
|
||||||
@ -875,6 +885,7 @@ shell_recorder_class_init (ShellRecorderClass *klass)
|
|||||||
static void
|
static void
|
||||||
recorder_pipeline_set_caps (RecorderPipeline *pipeline)
|
recorder_pipeline_set_caps (RecorderPipeline *pipeline)
|
||||||
{
|
{
|
||||||
|
ShellRecorder *recorder = pipeline->recorder;
|
||||||
GstCaps *caps;
|
GstCaps *caps;
|
||||||
|
|
||||||
/* The data is always native-endian xRGB; videoconvert
|
/* The data is always native-endian xRGB; videoconvert
|
||||||
@ -887,9 +898,9 @@ recorder_pipeline_set_caps (RecorderPipeline *pipeline)
|
|||||||
#else
|
#else
|
||||||
"format", G_TYPE_STRING, "xRGB",
|
"format", G_TYPE_STRING, "xRGB",
|
||||||
#endif
|
#endif
|
||||||
"framerate", GST_TYPE_FRACTION, pipeline->recorder->framerate, 1,
|
"framerate", GST_TYPE_FRACTION, recorder->framerate, 1,
|
||||||
"width", G_TYPE_INT, pipeline->recorder->area.width,
|
"width", G_TYPE_INT, recorder->capture_width,
|
||||||
"height", G_TYPE_INT, pipeline->recorder->area.height,
|
"height", G_TYPE_INT, recorder->capture_height,
|
||||||
NULL);
|
NULL);
|
||||||
g_object_set (pipeline->src, "caps", caps, NULL);
|
g_object_set (pipeline->src, "caps", caps, NULL);
|
||||||
gst_caps_unref (caps);
|
gst_caps_unref (caps);
|
||||||
@ -1496,6 +1507,11 @@ shell_recorder_set_area (ShellRecorder *recorder,
|
|||||||
recorder->area.height = CLAMP (height,
|
recorder->area.height = CLAMP (height,
|
||||||
0, recorder->stage_height - recorder->area.y);
|
0, recorder->stage_height - recorder->area.y);
|
||||||
|
|
||||||
|
clutter_stage_get_capture_final_size (recorder->stage, &recorder->area,
|
||||||
|
&recorder->capture_width,
|
||||||
|
&recorder->capture_height,
|
||||||
|
&recorder->scale);
|
||||||
|
|
||||||
/* This breaks the recording but tweaking the GStreamer pipeline a bit
|
/* This breaks the recording but tweaking the GStreamer pipeline a bit
|
||||||
* might make it work, at least if the codec can handle a stream where
|
* might make it work, at least if the codec can handle a stream where
|
||||||
* the frame size changes in the middle.
|
* the frame size changes in the middle.
|
||||||
|
@ -222,29 +222,32 @@ do_grab_screenshot (ShellScreenshot *screenshot,
|
|||||||
int height)
|
int height)
|
||||||
{
|
{
|
||||||
ShellScreenshotPrivate *priv = screenshot->priv;
|
ShellScreenshotPrivate *priv = screenshot->priv;
|
||||||
|
cairo_rectangle_int_t screenshot_rect = { x, y, width, height };
|
||||||
ClutterCapture *captures;
|
ClutterCapture *captures;
|
||||||
int n_captures;
|
int n_captures;
|
||||||
int i;
|
int i;
|
||||||
|
|
||||||
clutter_stage_capture (stage, FALSE,
|
if (!clutter_stage_capture (stage, FALSE,
|
||||||
&(cairo_rectangle_int_t) {
|
&screenshot_rect,
|
||||||
.x = x,
|
&captures,
|
||||||
.y = y,
|
&n_captures))
|
||||||
.width = width,
|
|
||||||
.height = height
|
|
||||||
},
|
|
||||||
&captures,
|
|
||||||
&n_captures);
|
|
||||||
|
|
||||||
if (n_captures == 0)
|
|
||||||
return;
|
return;
|
||||||
else if (n_captures == 1)
|
|
||||||
|
if (n_captures == 1)
|
||||||
priv->image = cairo_surface_reference (captures[0].image);
|
priv->image = cairo_surface_reference (captures[0].image);
|
||||||
else
|
else
|
||||||
priv->image = shell_util_composite_capture_images (captures,
|
{
|
||||||
n_captures,
|
float target_scale;
|
||||||
x, y,
|
|
||||||
width, height);
|
clutter_stage_get_capture_final_size (stage, &screenshot_rect,
|
||||||
|
&width, &height, &target_scale);
|
||||||
|
priv->image = shell_util_composite_capture_images (captures,
|
||||||
|
n_captures,
|
||||||
|
x, y,
|
||||||
|
width, height,
|
||||||
|
target_scale);
|
||||||
|
}
|
||||||
|
|
||||||
priv->datetime = g_date_time_new_now_local ();
|
priv->datetime = g_date_time_new_now_local ();
|
||||||
|
|
||||||
for (i = 0; i < n_captures; i++)
|
for (i = 0; i < n_captures; i++)
|
||||||
|
@ -462,31 +462,20 @@ shell_util_composite_capture_images (ClutterCapture *captures,
|
|||||||
int n_captures,
|
int n_captures,
|
||||||
int x,
|
int x,
|
||||||
int y,
|
int y,
|
||||||
int width,
|
int target_width,
|
||||||
int height)
|
int target_height,
|
||||||
|
float target_scale)
|
||||||
{
|
{
|
||||||
int i;
|
int i;
|
||||||
double target_scale;
|
|
||||||
cairo_format_t format;
|
cairo_format_t format;
|
||||||
cairo_surface_t *image;
|
cairo_surface_t *image;
|
||||||
cairo_t *cr;
|
cairo_t *cr;
|
||||||
|
|
||||||
g_assert (n_captures > 0);
|
g_assert (n_captures > 0);
|
||||||
|
g_assert (target_scale > 0.0f);
|
||||||
target_scale = 0.0;
|
|
||||||
for (i = 0; i < n_captures; i++)
|
|
||||||
{
|
|
||||||
ClutterCapture *capture = &captures[i];
|
|
||||||
double capture_scale = 1.0;
|
|
||||||
|
|
||||||
cairo_surface_get_device_scale (capture->image, &capture_scale, NULL);
|
|
||||||
target_scale = MAX (target_scale, capture_scale);
|
|
||||||
}
|
|
||||||
|
|
||||||
format = cairo_image_surface_get_format (captures[0].image);
|
format = cairo_image_surface_get_format (captures[0].image);
|
||||||
image = cairo_image_surface_create (format,
|
image = cairo_image_surface_create (format, target_width, target_height);
|
||||||
width * target_scale,
|
|
||||||
height * target_scale);
|
|
||||||
cairo_surface_set_device_scale (image, target_scale, target_scale);
|
cairo_surface_set_device_scale (image, target_scale, target_scale);
|
||||||
|
|
||||||
cr = cairo_create (image);
|
cr = cairo_create (image);
|
||||||
|
@ -53,8 +53,9 @@ cairo_surface_t * shell_util_composite_capture_images (ClutterCapture *captures
|
|||||||
int n_captures,
|
int n_captures,
|
||||||
int x,
|
int x,
|
||||||
int y,
|
int y,
|
||||||
int width,
|
int target_width,
|
||||||
int height);
|
int target_height,
|
||||||
|
float target_scale);
|
||||||
|
|
||||||
void shell_util_check_cloexec_fds (void);
|
void shell_util_check_cloexec_fds (void);
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user