[Spice-devel] [RFC PATCH 13/16] stream-channel: Support client connection/disconnection
Frediano Ziglio
fziglio at redhat.com
Wed Jan 25 12:42:36 UTC 2017
On new client we must restart the stream so new clients
can receive correct data without having to wait next full
screen (which on idle screen could take ages).
On disconnection we should tell the guest to stop streaming
not wasting resources to stream not needed data.
Signed-off-by: Frediano Ziglio <fziglio at redhat.com>
---
server/stream-channel.c | 75 ++++++++++++++++++++++++++++++++++++++++++-
1 file changed, 75 insertions(+)
diff --git a/server/stream-channel.c b/server/stream-channel.c
index 87aebbb..0b87939 100644
--- a/server/stream-channel.c
+++ b/server/stream-channel.c
@@ -105,8 +105,32 @@ stream_channel_client_init(StreamChannelClient *client)
}
static void
+ask_new_stream(StreamChannel *channel, StreamMsgStart *start)
+{
+ if (channel->start_cb) {
+ channel->start_cb(channel->start_opaque, start, channel);
+ }
+}
+
+static void
stream_channel_client_on_disconnect(RedChannelClient *rcc)
{
+ RedChannel *red_channel = red_channel_client_get_channel(rcc);
+
+ // if there are still some client connected keep streaming
+ // TODO, maybe would be worth sending new codecs if they are better
+ if (red_channel_is_connected(red_channel)) {
+ return;
+ }
+
+ StreamChannel *channel = STREAM_CHANNEL(red_channel);
+ channel->stream_id = -1;
+ channel->width = 0;
+ channel->height = 0;
+
+ // send stream stop to device
+ StreamMsgStart start = { 0, };
+ ask_new_stream(channel, &start);
}
static StreamChannelClient*
@@ -262,6 +286,49 @@ stream_channel_new(RedsState *server)
NULL);
}
+// find common codecs supported by all clients
+static StreamMsgStart*
+stream_channel_get_supported_codecs(StreamChannel *channel)
+{
+ GListIter iter;
+ RedChannelClient *rcc;
+ int codec;
+
+ static const uint16_t codec2cap[] = {
+ 0, // invalid
+ SPICE_DISPLAY_CAP_CODEC_MJPEG,
+ SPICE_DISPLAY_CAP_CODEC_VP8,
+ SPICE_DISPLAY_CAP_CODEC_H264,
+ SPICE_DISPLAY_CAP_CODEC_VP9,
+ };
+
+ char supported[SPICE_N_ELEMENTS(codec2cap)];
+ memset(supported, 1, sizeof(supported));
+
+ FOREACH_CLIENT(channel, iter, rcc) {
+ for (codec = 1; codec < SPICE_N_ELEMENTS(codec2cap); ++codec) {
+ // if do not support codec delete from list
+ if (!red_channel_client_test_remote_cap(rcc, codec2cap[codec])) {
+ supported[codec] = 0;
+ }
+ }
+ }
+
+ // surely mjpeg is supported
+ supported[SPICE_VIDEO_CODEC_TYPE_MJPEG] = 1;
+
+ StreamMsgStart *start = spice_malloc0(sizeof(*start) + sizeof(start->codecs[0]) * 256);
+ int num = 0;
+ for (codec = 1; codec < SPICE_N_ELEMENTS(codec2cap); ++codec) {
+ if (supported[codec]) {
+ start->codecs[num++] = codec;
+ }
+ }
+ start->num_codecs = num;
+
+ return start;
+}
+
static void
stream_channel_connect(RedChannel *red_channel, RedClient *red_client, RedsStream *stream,
int migration,
@@ -279,6 +346,14 @@ stream_channel_connect(RedChannel *red_channel, RedClient *red_client, RedsStrea
caps, num_caps);
spice_return_if_fail(client != NULL);
+ // ask new stream
+ StreamMsgStart* start = stream_channel_get_supported_codecs(channel);
+ // send in any case, even if list is not changed
+ // notify device about changes
+ ask_new_stream(channel, start);
+ free(start);
+
+
// TODO set capabilities like SPICE_DISPLAY_CAP_MONITORS_CONFIG
// see guest_set_client_capabilities
RedChannelClient *rcc = RED_CHANNEL_CLIENT(client);
--
git-series 0.9.1
More information about the Spice-devel
mailing list