shell-recorder: Support specifying the recorded area
Currently we will always record the entire screen. It has been requested to support recording a specified area analogous to the screenshot API as well, so add a set_area() method which allows this. https://bugzilla.gnome.org/show_bug.cgi?id=696247
This commit is contained in:
parent
98240c2857
commit
52dd030087
@ -50,6 +50,8 @@ struct _ShellRecorder {
|
|||||||
RecorderState state;
|
RecorderState state;
|
||||||
|
|
||||||
ClutterStage *stage;
|
ClutterStage *stage;
|
||||||
|
gboolean custom_area;
|
||||||
|
cairo_rectangle_int_t area;
|
||||||
int stage_width;
|
int stage_width;
|
||||||
int stage_height;
|
int stage_height;
|
||||||
|
|
||||||
@ -429,10 +431,10 @@ recorder_draw_cursor (ShellRecorder *recorder,
|
|||||||
/* We don't show a cursor unless the hot spot is in the frame; this
|
/* We don't show a cursor unless the hot spot is in the frame; this
|
||||||
* means that sometimes we aren't going to draw a cursor even when
|
* means that sometimes we aren't going to draw a cursor even when
|
||||||
* there is a little bit overlapping within the stage */
|
* there is a little bit overlapping within the stage */
|
||||||
if (recorder->pointer_x < 0 ||
|
if (recorder->pointer_x < recorder->area.x ||
|
||||||
recorder->pointer_y < 0 ||
|
recorder->pointer_y < recorder->area.y ||
|
||||||
recorder->pointer_x >= recorder->stage_width ||
|
recorder->pointer_x >= recorder->area.x + recorder->area.width ||
|
||||||
recorder->pointer_y >= recorder->stage_height)
|
recorder->pointer_y >= recorder->area.y + recorder->area.height)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
if (!recorder->cursor_image)
|
if (!recorder->cursor_image)
|
||||||
@ -444,15 +446,15 @@ recorder_draw_cursor (ShellRecorder *recorder,
|
|||||||
gst_buffer_map (buffer, &info, GST_MAP_WRITE);
|
gst_buffer_map (buffer, &info, GST_MAP_WRITE);
|
||||||
surface = cairo_image_surface_create_for_data (info.data,
|
surface = cairo_image_surface_create_for_data (info.data,
|
||||||
CAIRO_FORMAT_ARGB32,
|
CAIRO_FORMAT_ARGB32,
|
||||||
recorder->stage_width,
|
recorder->area.width,
|
||||||
recorder->stage_height,
|
recorder->area.height,
|
||||||
recorder->stage_width * 4);
|
recorder->area.width * 4);
|
||||||
|
|
||||||
cr = cairo_create (surface);
|
cr = cairo_create (surface);
|
||||||
cairo_set_source_surface (cr,
|
cairo_set_source_surface (cr,
|
||||||
recorder->cursor_image,
|
recorder->cursor_image,
|
||||||
recorder->pointer_x - recorder->cursor_hot_x,
|
recorder->pointer_x - recorder->cursor_hot_x - recorder->area.x,
|
||||||
recorder->pointer_y - recorder->cursor_hot_y);
|
recorder->pointer_y - recorder->cursor_hot_y - recorder->area.y);
|
||||||
cairo_paint (cr);
|
cairo_paint (cr);
|
||||||
|
|
||||||
cairo_destroy (cr);
|
cairo_destroy (cr);
|
||||||
@ -555,12 +557,13 @@ recorder_record_frame (ShellRecorder *recorder)
|
|||||||
|
|
||||||
recorder->last_frame_time = now;
|
recorder->last_frame_time = now;
|
||||||
|
|
||||||
size = recorder->stage_width * recorder->stage_height * 4;
|
size = recorder->area.width * recorder->area.height * 4;
|
||||||
|
|
||||||
data = g_malloc (recorder->stage_width * 4 * recorder->stage_height);
|
data = g_malloc (recorder->area.width * 4 * recorder->area.height);
|
||||||
cogl_read_pixels (0, 0, /* x/y */
|
cogl_read_pixels (recorder->area.x,
|
||||||
recorder->stage_width,
|
recorder->area.y,
|
||||||
recorder->stage_height,
|
recorder->area.width,
|
||||||
|
recorder->area.height,
|
||||||
COGL_READ_PIXELS_COLOR_BUFFER,
|
COGL_READ_PIXELS_COLOR_BUFFER,
|
||||||
CLUTTER_CAIRO_FORMAT_ARGB32,
|
CLUTTER_CAIRO_FORMAT_ARGB32,
|
||||||
data);
|
data);
|
||||||
@ -616,6 +619,14 @@ recorder_update_size (ShellRecorder *recorder)
|
|||||||
clutter_actor_get_allocation_box (CLUTTER_ACTOR (recorder->stage), &allocation);
|
clutter_actor_get_allocation_box (CLUTTER_ACTOR (recorder->stage), &allocation);
|
||||||
recorder->stage_width = (int)(0.5 + allocation.x2 - allocation.x1);
|
recorder->stage_width = (int)(0.5 + allocation.x2 - allocation.x1);
|
||||||
recorder->stage_height = (int)(0.5 + allocation.y2 - allocation.y1);
|
recorder->stage_height = (int)(0.5 + allocation.y2 - allocation.y1);
|
||||||
|
|
||||||
|
if (!recorder->custom_area)
|
||||||
|
{
|
||||||
|
recorder->area.x = 0;
|
||||||
|
recorder->area.y = 0;
|
||||||
|
recorder->area.width = recorder->stage_width;
|
||||||
|
recorder->area.height = recorder->stage_height;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
static void
|
static void
|
||||||
@ -1126,8 +1137,8 @@ recorder_pipeline_set_caps (RecorderPipeline *pipeline)
|
|||||||
"bpp", G_TYPE_INT, 32,
|
"bpp", G_TYPE_INT, 32,
|
||||||
"depth", G_TYPE_INT, 24,
|
"depth", G_TYPE_INT, 24,
|
||||||
"framerate", GST_TYPE_FRACTION, pipeline->recorder->framerate, 1,
|
"framerate", GST_TYPE_FRACTION, pipeline->recorder->framerate, 1,
|
||||||
"width", G_TYPE_INT, pipeline->recorder->stage_width,
|
"width", G_TYPE_INT, pipeline->recorder->area.width,
|
||||||
"height", G_TYPE_INT, pipeline->recorder->stage_height,
|
"height", G_TYPE_INT, pipeline->recorder->area.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);
|
||||||
@ -1705,6 +1716,31 @@ shell_recorder_set_pipeline (ShellRecorder *recorder,
|
|||||||
recorder_set_pipeline (recorder, pipeline);
|
recorder_set_pipeline (recorder, pipeline);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
shell_recorder_set_area (ShellRecorder *recorder,
|
||||||
|
int x,
|
||||||
|
int y,
|
||||||
|
int width,
|
||||||
|
int height)
|
||||||
|
{
|
||||||
|
g_return_if_fail (SHELL_IS_RECORDER (recorder));
|
||||||
|
|
||||||
|
recorder->custom_area = TRUE;
|
||||||
|
recorder->area.x = CLAMP (x, 0, recorder->stage_width);
|
||||||
|
recorder->area.y = CLAMP (y, 0, recorder->stage_height);
|
||||||
|
recorder->area.width = CLAMP (width,
|
||||||
|
0, recorder->stage_width - recorder->area.x);
|
||||||
|
recorder->area.height = CLAMP (height,
|
||||||
|
0, recorder->stage_height - recorder->area.y);
|
||||||
|
|
||||||
|
/* 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
|
||||||
|
* the frame size changes in the middle.
|
||||||
|
*/
|
||||||
|
if (recorder->current_pipeline)
|
||||||
|
recorder_pipeline_set_caps (recorder->current_pipeline);
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* shell_recorder_record:
|
* shell_recorder_record:
|
||||||
* @recorder: the #ShellRecorder
|
* @recorder: the #ShellRecorder
|
||||||
|
@ -36,6 +36,11 @@ void shell_recorder_set_file_template (ShellRecorder *recorder,
|
|||||||
const char *file_template);
|
const char *file_template);
|
||||||
void shell_recorder_set_pipeline (ShellRecorder *recorder,
|
void shell_recorder_set_pipeline (ShellRecorder *recorder,
|
||||||
const char *pipeline);
|
const char *pipeline);
|
||||||
|
void shell_recorder_set_area (ShellRecorder *recorder,
|
||||||
|
int x,
|
||||||
|
int y,
|
||||||
|
int width,
|
||||||
|
int height);
|
||||||
gboolean shell_recorder_record (ShellRecorder *recorder,
|
gboolean shell_recorder_record (ShellRecorder *recorder,
|
||||||
char **filename_used);
|
char **filename_used);
|
||||||
void shell_recorder_close (ShellRecorder *recorder);
|
void shell_recorder_close (ShellRecorder *recorder);
|
||||||
|
Loading…
x
Reference in New Issue
Block a user