~ubuntu-branches/ubuntu/trusty/gnome-shell/trusty-proposed

« back to all changes in this revision

Viewing changes to src/shell-recorder.c

Tags: upstream-3.3.90
ImportĀ upstreamĀ versionĀ 3.3.90

Show diffs side-by-side

added added

removed removed

Lines of Context:
12
12
 
13
13
#include "shell-recorder-src.h"
14
14
#include "shell-recorder.h"
 
15
#include "shell-screen-grabber.h"
15
16
 
16
17
#include <clutter/x11/clutter-x11.h>
17
18
#include <X11/extensions/Xfixes.h>
47
48
  int stage_width;
48
49
  int stage_height;
49
50
 
 
51
  ShellScreenGrabber *grabber;
 
52
 
50
53
  gboolean have_pointer;
51
54
  int pointer_x;
52
55
  int pointer_y;
74
77
  GSList *pipelines; /* all pipelines */
75
78
 
76
79
  GstClockTime start_time; /* When we started recording (adjusted for pauses) */
 
80
  GstClockTime last_frame_time; /* Timestamp for the last frame */
77
81
  GstClockTime pause_time; /* When the pipeline was paused */
78
82
 
79
83
  /* GSource IDs for different timeouts and idles */
114
118
 
115
119
G_DEFINE_TYPE(ShellRecorder, shell_recorder, G_TYPE_OBJECT);
116
120
 
117
 
/* The number of frames per second we configure for the GStreamer pipeline.
118
 
 * (the number of frames we actually write into the GStreamer pipeline is
119
 
 * based entirely on how fast clutter is drawing.) Using 60fps seems high
120
 
 * but the observed smoothness is a lot better than for 30fps when encoding
121
 
 * as theora for a minimal size increase. This may be an artifact of the
122
 
 * encoding process.
 
121
/* The default value of the target frame rate; we'll never record more
 
122
 * than this many frames per second, though we may record less if the
 
123
 * screen isn't being redrawn. 30 is a compromise between smoothness
 
124
 * and the size of the recording.
123
125
 */
124
 
#define DEFAULT_FRAMES_PER_SECOND 15
 
126
#define DEFAULT_FRAMES_PER_SECOND 30
125
127
 
126
128
/* The time (in milliseconds) between querying the server for the cursor
127
129
 * position.
145
147
 * (Theora does have some support for frames at non-uniform times, but
146
148
 * things seem to break down if there are large gaps.)
147
149
 */
148
 
#define DEFAULT_PIPELINE "videorate ! vp8enc quality=10 speed=2 threads=%T ! queue ! webmmux"
 
150
#define DEFAULT_PIPELINE "vp8enc quality=8 speed=6 threads=%T ! queue ! webmmux"
149
151
 
150
152
/* The default filename pattern. Example shell-20090311b-2.webm
151
153
 */
265
267
  recorder->recording_icon = create_recording_icon ();
266
268
  recorder->memory_target = get_memory_target();
267
269
 
 
270
  recorder->grabber = shell_screen_grabber_new ();
 
271
 
268
272
  recorder->state = RECORDER_STATE_CLOSED;
269
273
  recorder->framerate = DEFAULT_FRAMES_PER_SECOND;
270
274
}
296
300
  recorder_set_pipeline (recorder, NULL);
297
301
  recorder_set_filename (recorder, NULL);
298
302
 
 
303
  g_object_unref (recorder->grabber);
 
304
 
299
305
  cogl_handle_unref (recorder->recording_icon);
300
306
 
301
307
  G_OBJECT_CLASS (shell_recorder_parent_class)->finalize (object);
341
347
           * seems like a bad idea.
342
348
           */
343
349
          recorder->only_paint = TRUE;
344
 
          clutter_redraw (recorder->stage);
 
350
          clutter_stage_ensure_redraw (recorder->stage);
345
351
          recorder->only_paint = FALSE;
346
352
        }
347
353
    }
518
524
  GstBuffer *buffer;
519
525
  guint8 *data;
520
526
  guint size;
 
527
  GstClockTime now;
 
528
 
 
529
  /* If we get into the red zone, stop buffering new frames; 13/16 is
 
530
  * a bit more than the 3/4 threshold for a red indicator to keep the
 
531
  * indicator from flashing between red and yellow. */
 
532
  if (recorder->memory_used > (recorder->memory_target * 13) / 16)
 
533
    return;
 
534
 
 
535
  /* Drop frames to get down to something like the target frame rate; since frames
 
536
   * are generated with VBlank sync, we don't have full control anyways, so we just
 
537
   * drop frames if the interval since the last frame is less than 75% of the
 
538
   * desired inter-frame interval.
 
539
   */
 
540
  now = get_wall_time();
 
541
  if (now - recorder->last_frame_time < (3 * 1000000000LL / (4 * recorder->framerate)))
 
542
    return;
 
543
 
 
544
  recorder->last_frame_time = now;
521
545
 
522
546
  size = recorder->stage_width * recorder->stage_height * 4;
523
 
  data = g_malloc (size);
 
547
 
 
548
  data = shell_screen_grabber_grab (recorder->grabber,
 
549
                                    0, 0, recorder->stage_width, recorder->stage_height);
524
550
 
525
551
  buffer = gst_buffer_new();
526
552
  GST_BUFFER_SIZE(buffer) = size;
527
553
  GST_BUFFER_MALLOCDATA(buffer) = GST_BUFFER_DATA(buffer) = data;
528
554
 
529
 
  GST_BUFFER_TIMESTAMP(buffer) = get_wall_time() - recorder->start_time;
530
 
 
531
 
  cogl_read_pixels (0, 0,
532
 
                    recorder->stage_width, recorder->stage_height,
533
 
                    COGL_READ_PIXELS_COLOR_BUFFER,
534
 
                    CLUTTER_CAIRO_FORMAT_ARGB32,
535
 
                    data);
 
555
  GST_BUFFER_TIMESTAMP(buffer) = now - recorder->start_time;
536
556
 
537
557
  recorder_draw_cursor (recorder, buffer);
538
558
 
1558
1578
 * @recorder: the #ShellRecorder
1559
1579
 * @framerate: Framerate used for resulting video in frames-per-second.
1560
1580
 *
1561
 
 * Sets the number of frames per second we configure for the GStreamer pipeline.
 
1581
 * Sets the number of frames per second we try to record. Less frames
 
1582
 * will be recorded when the screen doesn't need to be redrawn this
 
1583
 * quickly. (This value will also be set as the framerate for the
 
1584
 * GStreamer pipeline; whether that has an effect on the resulting
 
1585
 * video will depend on the details of the pipeline and the codec. The
 
1586
 * default encoding to webm format doesn't pay attention to the pipeline
 
1587
 * framerate.)
1562
1588
 *
1563
 
 * The default value is 15.
 
1589
 * The default value is 30.
1564
1590
 */
1565
1591
void
1566
1592
shell_recorder_set_framerate (ShellRecorder *recorder,
1619
1645
 * might be used to send the output to an icecast server
1620
1646
 * via shout2send or similar.
1621
1647
 *
1622
 
 * The default value is 'videorate ! theoraenc ! oggmux'
 
1648
 * The default value is 'vp8enc quality=8 speed=6 threads=%T ! queue ! webmmux'
1623
1649
 */
1624
1650
void
1625
1651
shell_recorder_set_pipeline (ShellRecorder *recorder,
1662
1688
       * pause
1663
1689
       */
1664
1690
      recorder->start_time = recorder->start_time + (get_wall_time() - recorder->pause_time);
 
1691
      recorder->last_frame_time = 0;
1665
1692
    }
1666
1693
  else
1667
1694
    {
1669
1696
        return FALSE;
1670
1697
 
1671
1698
      recorder->start_time = get_wall_time();
 
1699
      recorder->last_frame_time = 0;
1672
1700
    }
1673
1701
 
1674
1702
  recorder->state = RECORDER_STATE_RECORDING;