[Spice-devel] [PATCH 5/9] worker: move stream_agent_stop and friends

Frediano Ziglio fziglio at redhat.com
Tue Nov 17 08:37:51 PST 2015


From: Marc-André Lureau <marcandre.lureau at gmail.com>

---
 server/display-channel.h |   2 +
 server/red_worker.c      | 178 +----------------------------------------------
 server/stream.c          | 174 +++++++++++++++++++++++++++++++++++++++++++++
 server/stream.h          |   3 +
 4 files changed, 180 insertions(+), 177 deletions(-)

diff --git a/server/display-channel.h b/server/display-channel.h
index edbd4b9..ae8a900 100644
--- a/server/display-channel.h
+++ b/server/display-channel.h
@@ -252,6 +252,8 @@ void                       dcc_push_destroy_surface                  (DisplayCha
                                                                       uint32_t surface_id);
 void                       dcc_add_stream_agent_clip                 (DisplayChannelClient* dcc,
                                                                       StreamAgent *agent);
+void                       dcc_create_stream                         (DisplayChannelClient *dcc,
+                                                                      Stream *stream);
 
 typedef struct DrawablePipeItem {
     RingItem base;  /* link for a list of pipe items held by Drawable */
diff --git a/server/red_worker.c b/server/red_worker.c
index 6a331cb..5269752 100644
--- a/server/red_worker.c
+++ b/server/red_worker.c
@@ -80,7 +80,6 @@
 #define DISPLAY_FREE_LIST_DEFAULT_SIZE 128
 
 #define FPS_TEST_INTERVAL 1
-#define MAX_FPS 30
 
 #define ZLIB_DEFAULT_COMPRESSION_LEVEL 3
 #define MIN_GLZ_SIZE_FOR_ZLIB 100
@@ -1353,181 +1352,6 @@ static Stream *display_channel_stream_try_new(DisplayChannel *display)
     return stream;
 }
 
-static uint64_t red_stream_get_initial_bit_rate(DisplayChannelClient *dcc,
-                                                Stream *stream)
-{
-    char *env_bit_rate_str;
-    uint64_t bit_rate = 0;
-
-    env_bit_rate_str = getenv("SPICE_BIT_RATE");
-    if (env_bit_rate_str != NULL) {
-        double env_bit_rate;
-
-        errno = 0;
-        env_bit_rate = strtod(env_bit_rate_str, NULL);
-        if (errno == 0) {
-            bit_rate = env_bit_rate * 1024 * 1024;
-        } else {
-            spice_warning("error parsing SPICE_BIT_RATE: %s", strerror(errno));
-        }
-    }
-
-    if (!bit_rate) {
-        MainChannelClient *mcc;
-        uint64_t net_test_bit_rate;
-
-        mcc = red_client_get_main(RED_CHANNEL_CLIENT(dcc)->client);
-        net_test_bit_rate = main_channel_client_is_network_info_initialized(mcc) ?
-                                main_channel_client_get_bitrate_per_sec(mcc) :
-                                0;
-        bit_rate = MAX(dcc->streams_max_bit_rate, net_test_bit_rate);
-        if (bit_rate == 0) {
-            /*
-             * In case we are after a spice session migration,
-             * the low_bandwidth flag is retrieved from migration data.
-             * If the network info is not initialized due to another reason,
-             * the low_bandwidth flag is FALSE.
-             */
-            bit_rate = dcc->common.is_low_bandwidth ?
-                RED_STREAM_DEFAULT_LOW_START_BIT_RATE :
-                RED_STREAM_DEFAULT_HIGH_START_BIT_RATE;
-        }
-    }
-
-    spice_debug("base-bit-rate %.2f (Mbps)", bit_rate / 1024.0 / 1024.0);
-    /* dividing the available bandwidth among the active streams, and saving
-     * (1-RED_STREAM_CHANNEL_CAPACITY) of it for other messages */
-    return (RED_STREAM_CHANNEL_CAPACITY * bit_rate *
-            stream->width * stream->height) / DCC_TO_DC(dcc)->streams_size_total;
-}
-
-static uint32_t red_stream_mjpeg_encoder_get_roundtrip(void *opaque)
-{
-    StreamAgent *agent = opaque;
-    int roundtrip;
-
-    spice_assert(agent);
-    roundtrip = red_channel_client_get_roundtrip_ms(RED_CHANNEL_CLIENT(agent->dcc));
-    if (roundtrip < 0) {
-        MainChannelClient *mcc = red_client_get_main(RED_CHANNEL_CLIENT(agent->dcc)->client);
-
-        /*
-         * the main channel client roundtrip might not have been
-         * calculated (e.g., after migration). In such case,
-         * main_channel_client_get_roundtrip_ms returns 0.
-         */
-        roundtrip = main_channel_client_get_roundtrip_ms(mcc);
-    }
-
-    return roundtrip;
-}
-
-static uint32_t red_stream_mjpeg_encoder_get_source_fps(void *opaque)
-{
-    StreamAgent *agent = opaque;
-
-    spice_assert(agent);
-    return agent->stream->input_fps;
-}
-
-static void red_display_update_streams_max_latency(DisplayChannelClient *dcc, StreamAgent *remove_agent)
-{
-    uint32_t new_max_latency = 0;
-    int i;
-
-    if (dcc->streams_max_latency != remove_agent->client_required_latency) {
-        return;
-    }
-
-    dcc->streams_max_latency = 0;
-    if (DCC_TO_DC(dcc)->stream_count == 1) {
-        return;
-    }
-    for (i = 0; i < NUM_STREAMS; i++) {
-        StreamAgent *other_agent = &dcc->stream_agents[i];
-        if (other_agent == remove_agent || !other_agent->mjpeg_encoder) {
-            continue;
-        }
-        if (other_agent->client_required_latency > new_max_latency) {
-            new_max_latency = other_agent->client_required_latency;
-        }
-    }
-    dcc->streams_max_latency = new_max_latency;
-}
-
-static void red_display_stream_agent_stop(DisplayChannelClient *dcc, StreamAgent *agent)
-{
-    red_display_update_streams_max_latency(dcc, agent);
-    if (agent->mjpeg_encoder) {
-        mjpeg_encoder_destroy(agent->mjpeg_encoder);
-        agent->mjpeg_encoder = NULL;
-    }
-}
-
-static void red_stream_update_client_playback_latency(void *opaque, uint32_t delay_ms)
-{
-    StreamAgent *agent = opaque;
-    DisplayChannelClient *dcc = agent->dcc;
-
-    red_display_update_streams_max_latency(dcc, agent);
-
-    agent->client_required_latency = delay_ms;
-    if (delay_ms > agent->dcc->streams_max_latency) {
-         agent->dcc->streams_max_latency = delay_ms;
-    }
-    spice_debug("resetting client latency: %u", agent->dcc->streams_max_latency);
-    main_dispatcher_set_mm_time_latency(RED_CHANNEL_CLIENT(agent->dcc)->client, agent->dcc->streams_max_latency);
-}
-
-static void dcc_create_stream(DisplayChannelClient *dcc, Stream *stream)
-{
-    StreamAgent *agent = &dcc->stream_agents[get_stream_id(DCC_TO_DC(dcc), stream)];
-
-    stream->refs++;
-    spice_assert(region_is_empty(&agent->vis_region));
-    if (stream->current) {
-        agent->frames = 1;
-        region_clone(&agent->vis_region, &stream->current->tree_item.base.rgn);
-        region_clone(&agent->clip, &agent->vis_region);
-    } else {
-        agent->frames = 0;
-    }
-    agent->drops = 0;
-    agent->fps = MAX_FPS;
-    agent->dcc = dcc;
-
-    if (dcc->use_mjpeg_encoder_rate_control) {
-        MJpegEncoderRateControlCbs mjpeg_cbs;
-        uint64_t initial_bit_rate;
-
-        mjpeg_cbs.get_roundtrip_ms = red_stream_mjpeg_encoder_get_roundtrip;
-        mjpeg_cbs.get_source_fps = red_stream_mjpeg_encoder_get_source_fps;
-        mjpeg_cbs.update_client_playback_delay = red_stream_update_client_playback_latency;
-
-        initial_bit_rate = red_stream_get_initial_bit_rate(dcc, stream);
-        agent->mjpeg_encoder = mjpeg_encoder_new(initial_bit_rate, &mjpeg_cbs, agent);
-    } else {
-        agent->mjpeg_encoder = mjpeg_encoder_new(0, NULL, NULL);
-    }
-    red_channel_client_pipe_add(RED_CHANNEL_CLIENT(dcc), &agent->create_item);
-
-    if (red_channel_client_test_remote_cap(RED_CHANNEL_CLIENT(dcc), SPICE_DISPLAY_CAP_STREAM_REPORT)) {
-        StreamActivateReportItem *report_pipe_item = spice_malloc0(sizeof(*report_pipe_item));
-
-        agent->report_id = rand();
-        red_channel_pipe_item_init(RED_CHANNEL_CLIENT(dcc)->channel, &report_pipe_item->pipe_item,
-                                   PIPE_ITEM_TYPE_STREAM_ACTIVATE_REPORT);
-        report_pipe_item->stream_id = get_stream_id(DCC_TO_DC(dcc), stream);
-        red_channel_client_pipe_add(RED_CHANNEL_CLIENT(dcc), &report_pipe_item->pipe_item);
-    }
-#ifdef STREAM_STATS
-    memset(&agent->stats, 0, sizeof(StreamStats));
-    if (stream->current) {
-        agent->stats.start = stream->current->red_drawable->mm_time;
-    }
-#endif
-}
-
 static void display_channel_create_stream(DisplayChannel *display, Drawable *drawable)
 {
     DisplayChannelClient *dcc;
@@ -6872,7 +6696,7 @@ static void red_display_marshall_stream_end(RedChannelClient *rcc,
 
     red_channel_client_init_send_data(rcc, SPICE_MSG_DISPLAY_STREAM_DESTROY, NULL);
     destroy.id = get_stream_id(DCC_TO_DC(dcc), agent->stream);
-    red_display_stream_agent_stop(dcc, agent);
+    stream_agent_stop(dcc, agent);
     spice_marshall_msg_display_stream_destroy(base_marshaller, &destroy);
 }
 
diff --git a/server/stream.c b/server/stream.c
index 406111c..27d6d36 100644
--- a/server/stream.c
+++ b/server/stream.c
@@ -138,3 +138,177 @@ StreamClipItem *stream_clip_item_new(DisplayChannelClient* dcc, StreamAgent *age
     item->refs = 1;
     return item;
 }
+
+static void dcc_update_streams_max_latency(DisplayChannelClient *dcc, StreamAgent *remove_agent)
+{
+    uint32_t new_max_latency = 0;
+    int i;
+
+    if (dcc->streams_max_latency != remove_agent->client_required_latency) {
+        return;
+    }
+
+    dcc->streams_max_latency = 0;
+    if (DCC_TO_DC(dcc)->stream_count == 1) {
+        return;
+    }
+    for (i = 0; i < NUM_STREAMS; i++) {
+        StreamAgent *other_agent = &dcc->stream_agents[i];
+        if (other_agent == remove_agent || !other_agent->mjpeg_encoder) {
+            continue;
+        }
+        if (other_agent->client_required_latency > new_max_latency) {
+            new_max_latency = other_agent->client_required_latency;
+        }
+    }
+    dcc->streams_max_latency = new_max_latency;
+}
+
+static uint64_t red_stream_get_initial_bit_rate(DisplayChannelClient *dcc,
+                                                Stream *stream)
+{
+    char *env_bit_rate_str;
+    uint64_t bit_rate = 0;
+
+    env_bit_rate_str = getenv("SPICE_BIT_RATE");
+    if (env_bit_rate_str != NULL) {
+        double env_bit_rate;
+
+        errno = 0;
+        env_bit_rate = strtod(env_bit_rate_str, NULL);
+        if (errno == 0) {
+            bit_rate = env_bit_rate * 1024 * 1024;
+        } else {
+            spice_warning("error parsing SPICE_BIT_RATE: %s", strerror(errno));
+        }
+    }
+
+    if (!bit_rate) {
+        MainChannelClient *mcc;
+        uint64_t net_test_bit_rate;
+
+        mcc = red_client_get_main(RED_CHANNEL_CLIENT(dcc)->client);
+        net_test_bit_rate = main_channel_client_is_network_info_initialized(mcc) ?
+                                main_channel_client_get_bitrate_per_sec(mcc) :
+                                0;
+        bit_rate = MAX(dcc->streams_max_bit_rate, net_test_bit_rate);
+        if (bit_rate == 0) {
+            /*
+             * In case we are after a spice session migration,
+             * the low_bandwidth flag is retrieved from migration data.
+             * If the network info is not initialized due to another reason,
+             * the low_bandwidth flag is FALSE.
+             */
+            bit_rate = dcc->common.is_low_bandwidth ?
+                RED_STREAM_DEFAULT_LOW_START_BIT_RATE :
+                RED_STREAM_DEFAULT_HIGH_START_BIT_RATE;
+        }
+    }
+
+    spice_debug("base-bit-rate %.2f (Mbps)", bit_rate / 1024.0 / 1024.0);
+    /* dividing the available bandwidth among the active streams, and saving
+     * (1-RED_STREAM_CHANNEL_CAPACITY) of it for other messages */
+    return (RED_STREAM_CHANNEL_CAPACITY * bit_rate *
+            stream->width * stream->height) / DCC_TO_DC(dcc)->streams_size_total;
+}
+
+static uint32_t red_stream_mjpeg_encoder_get_roundtrip(void *opaque)
+{
+    StreamAgent *agent = opaque;
+    int roundtrip;
+
+    roundtrip = red_channel_client_get_roundtrip_ms(RED_CHANNEL_CLIENT(agent->dcc));
+    if (roundtrip < 0) {
+        MainChannelClient *mcc = red_client_get_main(RED_CHANNEL_CLIENT(agent->dcc)->client);
+
+        /*
+         * the main channel client roundtrip might not have been
+         * calculated (e.g., after migration). In such case,
+         * main_channel_client_get_roundtrip_ms returns 0.
+         */
+        roundtrip = main_channel_client_get_roundtrip_ms(mcc);
+    }
+
+    return roundtrip;
+}
+
+static uint32_t red_stream_mjpeg_encoder_get_source_fps(void *opaque)
+{
+    StreamAgent *agent = opaque;
+
+    return agent->stream->input_fps;
+}
+
+static void red_stream_update_client_playback_latency(void *opaque, uint32_t delay_ms)
+{
+    StreamAgent *agent = opaque;
+    DisplayChannelClient *dcc = agent->dcc;
+
+    dcc_update_streams_max_latency(dcc, agent);
+
+    agent->client_required_latency = delay_ms;
+    if (delay_ms > agent->dcc->streams_max_latency) {
+        agent->dcc->streams_max_latency = delay_ms;
+    }
+    spice_debug("resetting client latency: %u", agent->dcc->streams_max_latency);
+    main_dispatcher_set_mm_time_latency(RED_CHANNEL_CLIENT(agent->dcc)->client, agent->dcc->streams_max_latency);
+}
+
+void dcc_create_stream(DisplayChannelClient *dcc, Stream *stream)
+{
+    StreamAgent *agent = &dcc->stream_agents[get_stream_id(DCC_TO_DC(dcc), stream)];
+
+    spice_return_if_fail(region_is_empty(&agent->vis_region));
+
+    stream->refs++;
+    if (stream->current) {
+        agent->frames = 1;
+        region_clone(&agent->vis_region, &stream->current->tree_item.base.rgn);
+        region_clone(&agent->clip, &agent->vis_region);
+    } else {
+        agent->frames = 0;
+    }
+    agent->drops = 0;
+    agent->fps = MAX_FPS;
+    agent->dcc = dcc;
+
+    if (dcc->use_mjpeg_encoder_rate_control) {
+        MJpegEncoderRateControlCbs mjpeg_cbs;
+        uint64_t initial_bit_rate;
+
+        mjpeg_cbs.get_roundtrip_ms = red_stream_mjpeg_encoder_get_roundtrip;
+        mjpeg_cbs.get_source_fps = red_stream_mjpeg_encoder_get_source_fps;
+        mjpeg_cbs.update_client_playback_delay = red_stream_update_client_playback_latency;
+
+        initial_bit_rate = red_stream_get_initial_bit_rate(dcc, stream);
+        agent->mjpeg_encoder = mjpeg_encoder_new(initial_bit_rate, &mjpeg_cbs, agent);
+    } else {
+        agent->mjpeg_encoder = mjpeg_encoder_new(0, NULL, NULL);
+    }
+    red_channel_client_pipe_add(RED_CHANNEL_CLIENT(dcc), &agent->create_item);
+
+    if (red_channel_client_test_remote_cap(RED_CHANNEL_CLIENT(dcc), SPICE_DISPLAY_CAP_STREAM_REPORT)) {
+        StreamActivateReportItem *report_pipe_item = spice_malloc0(sizeof(*report_pipe_item));
+
+        agent->report_id = rand();
+        red_channel_pipe_item_init(RED_CHANNEL_CLIENT(dcc)->channel, &report_pipe_item->pipe_item,
+                                   PIPE_ITEM_TYPE_STREAM_ACTIVATE_REPORT);
+        report_pipe_item->stream_id = get_stream_id(DCC_TO_DC(dcc), stream);
+        red_channel_client_pipe_add(RED_CHANNEL_CLIENT(dcc), &report_pipe_item->pipe_item);
+    }
+#ifdef STREAM_STATS
+    memset(&agent->stats, 0, sizeof(StreamStats));
+    if (stream->current) {
+        agent->stats.start = stream->current->red_drawable->mm_time;
+    }
+#endif
+}
+
+void stream_agent_stop(DisplayChannelClient *dcc, StreamAgent *agent)
+{
+    dcc_update_streams_max_latency(dcc, agent);
+    if (agent->mjpeg_encoder) {
+        mjpeg_encoder_destroy(agent->mjpeg_encoder);
+        agent->mjpeg_encoder = NULL;
+    }
+}
diff --git a/server/stream.h b/server/stream.h
index 09df31b..c2007af 100644
--- a/server/stream.h
+++ b/server/stream.h
@@ -39,6 +39,7 @@
 #define RED_STREAM_CLIENT_REPORT_TIMEOUT 1000 // milliseconds
 #define RED_STREAM_DEFAULT_HIGH_START_BIT_RATE (10 * 1024 * 1024) // 10Mbps
 #define RED_STREAM_DEFAULT_LOW_START_BIT_RATE (2.5 * 1024 * 1024) // 2.5Mbps
+#define MAX_FPS 30
 
 /* move back to display_channel once struct private */
 typedef struct DisplayChannel DisplayChannel;
@@ -143,5 +144,7 @@ void                  stream_unref                                  (DisplayChan
 void                  stream_agent_unref                            (DisplayChannel *display,
                                                                      StreamAgent *agent);
 void                  stream_agent_stats_print                      (StreamAgent *agent);
+void                  stream_agent_stop                             (DisplayChannelClient *dcc,
+                                                                     StreamAgent *agent);
 
 #endif /* STREAM_H */
-- 
2.4.3



More information about the Spice-devel mailing list