ShellRecorder: drop frames to approximate the target framerate
Instead of adding every rendered frame into the recording, drop frames and only buffer and record enough frames to match the target framerate. Increase the default frame rate from 15 to 30, since now that we're actually enforcing framerate, it's noticeable that 15fps is not smooth. https://bugzilla.gnome.org/show_bug.cgi?id=669066
This commit is contained in:
parent
f2cc5cf152
commit
60d8683ae7
@ -108,7 +108,7 @@
|
|||||||
<schema id="org.gnome.shell.recorder" path="/org/gnome/shell/recorder/"
|
<schema id="org.gnome.shell.recorder" path="/org/gnome/shell/recorder/"
|
||||||
gettext-domain="@GETTEXT_PACKAGE@">
|
gettext-domain="@GETTEXT_PACKAGE@">
|
||||||
<key name="framerate" type="i">
|
<key name="framerate" type="i">
|
||||||
<default>15</default>
|
<default>30</default>
|
||||||
<_summary>Framerate used for recording screencasts.</_summary>
|
<_summary>Framerate used for recording screencasts.</_summary>
|
||||||
<_description>
|
<_description>
|
||||||
The framerate of the resulting screencast recordered
|
The framerate of the resulting screencast recordered
|
||||||
|
@ -77,6 +77,7 @@ struct _ShellRecorder {
|
|||||||
GSList *pipelines; /* all pipelines */
|
GSList *pipelines; /* all pipelines */
|
||||||
|
|
||||||
GstClockTime start_time; /* When we started recording (adjusted for pauses) */
|
GstClockTime start_time; /* When we started recording (adjusted for pauses) */
|
||||||
|
GstClockTime last_frame_time; /* Timestamp for the last frame */
|
||||||
GstClockTime pause_time; /* When the pipeline was paused */
|
GstClockTime pause_time; /* When the pipeline was paused */
|
||||||
|
|
||||||
/* GSource IDs for different timeouts and idles */
|
/* GSource IDs for different timeouts and idles */
|
||||||
@ -117,14 +118,12 @@ enum {
|
|||||||
|
|
||||||
G_DEFINE_TYPE(ShellRecorder, shell_recorder, G_TYPE_OBJECT);
|
G_DEFINE_TYPE(ShellRecorder, shell_recorder, G_TYPE_OBJECT);
|
||||||
|
|
||||||
/* The number of frames per second we configure for the GStreamer pipeline.
|
/* The default value of the target frame rate; we'll never record more
|
||||||
* (the number of frames we actually write into the GStreamer pipeline is
|
* than this many frames per second, though we may record less if the
|
||||||
* based entirely on how fast clutter is drawing.) Using 60fps seems high
|
* screen isn't being redrawn. 30 is a compromise between smoothness
|
||||||
* but the observed smoothness is a lot better than for 30fps when encoding
|
* and the size of the recording.
|
||||||
* as theora for a minimal size increase. This may be an artifact of the
|
|
||||||
* encoding process.
|
|
||||||
*/
|
*/
|
||||||
#define DEFAULT_FRAMES_PER_SECOND 15
|
#define DEFAULT_FRAMES_PER_SECOND 30
|
||||||
|
|
||||||
/* The time (in milliseconds) between querying the server for the cursor
|
/* The time (in milliseconds) between querying the server for the cursor
|
||||||
* position.
|
* position.
|
||||||
@ -525,6 +524,7 @@ recorder_record_frame (ShellRecorder *recorder)
|
|||||||
GstBuffer *buffer;
|
GstBuffer *buffer;
|
||||||
guint8 *data;
|
guint8 *data;
|
||||||
guint size;
|
guint size;
|
||||||
|
GstClockTime now;
|
||||||
|
|
||||||
/* If we get into the red zone, stop buffering new frames; 13/16 is
|
/* If we get into the red zone, stop buffering new frames; 13/16 is
|
||||||
* a bit more than the 3/4 threshold for a red indicator to keep the
|
* a bit more than the 3/4 threshold for a red indicator to keep the
|
||||||
@ -532,6 +532,17 @@ recorder_record_frame (ShellRecorder *recorder)
|
|||||||
if (recorder->memory_used > (recorder->memory_target * 13) / 16)
|
if (recorder->memory_used > (recorder->memory_target * 13) / 16)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
|
/* Drop frames to get down to something like the target frame rate; since frames
|
||||||
|
* are generated with VBlank sync, we don't have full control anyways, so we just
|
||||||
|
* drop frames if the interval since the last frame is less than 75% of the
|
||||||
|
* desired inter-frame interval.
|
||||||
|
*/
|
||||||
|
now = get_wall_time();
|
||||||
|
if (now - recorder->last_frame_time < (3 * 1000000000LL / (4 * recorder->framerate)))
|
||||||
|
return;
|
||||||
|
|
||||||
|
recorder->last_frame_time = now;
|
||||||
|
|
||||||
size = recorder->stage_width * recorder->stage_height * 4;
|
size = recorder->stage_width * recorder->stage_height * 4;
|
||||||
|
|
||||||
data = shell_screen_grabber_grab (recorder->grabber,
|
data = shell_screen_grabber_grab (recorder->grabber,
|
||||||
@ -541,8 +552,7 @@ recorder_record_frame (ShellRecorder *recorder)
|
|||||||
GST_BUFFER_SIZE(buffer) = size;
|
GST_BUFFER_SIZE(buffer) = size;
|
||||||
GST_BUFFER_MALLOCDATA(buffer) = GST_BUFFER_DATA(buffer) = data;
|
GST_BUFFER_MALLOCDATA(buffer) = GST_BUFFER_DATA(buffer) = data;
|
||||||
|
|
||||||
GST_BUFFER_TIMESTAMP(buffer) = get_wall_time() - recorder->start_time;
|
GST_BUFFER_TIMESTAMP(buffer) = now - recorder->start_time;
|
||||||
|
|
||||||
|
|
||||||
recorder_draw_cursor (recorder, buffer);
|
recorder_draw_cursor (recorder, buffer);
|
||||||
|
|
||||||
@ -1568,9 +1578,15 @@ shell_recorder_new (ClutterStage *stage)
|
|||||||
* @recorder: the #ShellRecorder
|
* @recorder: the #ShellRecorder
|
||||||
* @framerate: Framerate used for resulting video in frames-per-second.
|
* @framerate: Framerate used for resulting video in frames-per-second.
|
||||||
*
|
*
|
||||||
* Sets the number of frames per second we configure for the GStreamer pipeline.
|
* Sets the number of frames per second we try to record. Less frames
|
||||||
|
* will be recorded when the screen doesn't need to be redrawn this
|
||||||
|
* quickly. (This value will also be set as the framerate for the
|
||||||
|
* GStreamer pipeline; whether that has an effect on the resulting
|
||||||
|
* video will depend on the details of the pipeline and the codec. The
|
||||||
|
* default encoding to webm format doesn't pay attention to the pipeline
|
||||||
|
* framerate.)
|
||||||
*
|
*
|
||||||
* The default value is 15.
|
* The default value is 30.
|
||||||
*/
|
*/
|
||||||
void
|
void
|
||||||
shell_recorder_set_framerate (ShellRecorder *recorder,
|
shell_recorder_set_framerate (ShellRecorder *recorder,
|
||||||
@ -1672,6 +1688,7 @@ shell_recorder_record (ShellRecorder *recorder)
|
|||||||
* pause
|
* pause
|
||||||
*/
|
*/
|
||||||
recorder->start_time = recorder->start_time + (get_wall_time() - recorder->pause_time);
|
recorder->start_time = recorder->start_time + (get_wall_time() - recorder->pause_time);
|
||||||
|
recorder->last_frame_time = 0;
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
@ -1679,6 +1696,7 @@ shell_recorder_record (ShellRecorder *recorder)
|
|||||||
return FALSE;
|
return FALSE;
|
||||||
|
|
||||||
recorder->start_time = get_wall_time();
|
recorder->start_time = get_wall_time();
|
||||||
|
recorder->last_frame_time = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
recorder->state = RECORDER_STATE_RECORDING;
|
recorder->state = RECORDER_STATE_RECORDING;
|
||||||
|
Loading…
Reference in New Issue
Block a user