[Spice-devel] [PATCH spice-server 14/28] red_worker: stream - update periodically the input frame rate

Yonit Halperin yhalperi at redhat.com
Tue Feb 26 10:04:00 PST 2013


Periodically calculate the rate of frames arriving from the guest to the
server.
---
 server/red_worker.c | 36 +++++++++++++++++++++++++++++++++++-
 1 file changed, 35 insertions(+), 1 deletion(-)

diff --git a/server/red_worker.c b/server/red_worker.c
index c992688..82f2fc9 100644
--- a/server/red_worker.c
+++ b/server/red_worker.c
@@ -115,6 +115,7 @@
 #define RED_STREAM_GRADUAL_FRAMES_START_CONDITION 0.2
 #define RED_STREAM_FRAMES_RESET_CONDITION 100
 #define RED_STREAM_MIN_SIZE (96 * 96)
+#define RED_STREAM_INPUT_FPS_TIMEOUT (5 * 1000) // 5 sec
 
 #define FPS_TEST_INTERVAL 1
 #define MAX_FPS 30
@@ -432,6 +433,11 @@ struct Stream {
     Stream *next;
     RingItem link;
     int bit_rate;
+
+    SpiceTimer *input_fps_timer;
+    uint32_t num_input_frames;
+    uint64_t input_fps_timer_start;
+    uint32_t input_fps;
 };
 
 typedef struct StreamAgent {
@@ -1063,6 +1069,7 @@ static void dump_bitmap(RedWorker *worker, SpiceBitmap *bitmap, uint32_t group_i
 #endif
 
 static void red_push_monitors_config(DisplayChannelClient *dcc);
+static inline uint64_t red_now(void);
 
 /*
  * Macros to make iterating over stuff easier
@@ -2477,6 +2484,9 @@ static int is_same_drawable(RedWorker *worker, Drawable *d1, Drawable *d2)
 
 static inline void red_free_stream(RedWorker *worker, Stream *stream)
 {
+    if (stream->input_fps_timer) {
+        spice_timer_remove(stream->input_fps_timer);
+    }
     stream->next = worker->free_streams;
     worker->free_streams = stream;
 }
@@ -2555,6 +2565,7 @@ static void red_attach_stream(RedWorker *worker, Drawable *drawable, Stream *str
     stream->current = drawable;
     drawable->stream = stream;
     stream->last_time = drawable->creation_time;
+    stream->num_input_frames++;
 
     WORKER_FOREACH_DCC(worker, item, dcc) {
         StreamAgent *agent;
@@ -2892,6 +2903,24 @@ static void red_display_create_stream(DisplayChannelClient *dcc, Stream *stream)
     red_channel_client_pipe_add(&dcc->common.base, &agent->create_item);
 }
 
+static void red_stream_input_fps_timer_cb(void *opaque)
+{
+    Stream *stream = opaque;
+    uint64_t now = red_now();
+    double duration_sec;
+
+    spice_assert(opaque);
+    if (now == stream->input_fps_timer_start) {
+        spice_warning("timer start and expiry time are equal");
+        return;
+    }
+    duration_sec = (now - stream->input_fps_timer_start)/(1000.0*1000*1000);
+    stream->input_fps = stream->num_input_frames / duration_sec;
+    spice_debug("input-fps=%u", stream->input_fps);
+    stream->num_input_frames = 0;
+    stream->input_fps_timer_start = now;
+}
+
 /* TODO: we create the stream even if dcc is NULL, i.e. no client - or
  * maybe we can't reach this function in that case? question: do we want to? */
 static void red_create_stream(RedWorker *worker, Drawable *drawable)
@@ -2925,7 +2954,12 @@ static void red_create_stream(RedWorker *worker, Drawable *drawable)
     SpiceBitmap *bitmap = &drawable->red_drawable->u.copy.src_bitmap->u.bitmap;
     stream->top_down = !!(bitmap->flags & SPICE_BITMAP_FLAGS_TOP_DOWN);
     drawable->stream = stream;
-
+    stream->input_fps_timer = spice_timer_queue_add(red_stream_input_fps_timer_cb, stream);
+    spice_assert(stream->input_fps_timer);
+    spice_timer_set(stream->input_fps_timer, RED_STREAM_INPUT_FPS_TIMEOUT);
+    stream->num_input_frames = 0;
+    stream->input_fps_timer_start = red_now();
+    stream->input_fps = MAX_FPS;
     WORKER_FOREACH_DCC(worker, dcc_ring_item, dcc) {
         red_display_create_stream(dcc, stream);
     }
-- 
1.8.1



More information about the Spice-devel mailing list