[Spice-devel] [RFC spice-server 3/3] streaming: Restart guest video streams on video-codec changes
Kevin Pouget
kpouget at redhat.com
Tue Aug 6 15:34:47 UTC 2019
This patch resets the host and guest video streams when the client
changes the preferred video-codecs or when the host admin updates the
list of video-codecs allowed.
TODO: restart only the streams of the client that changed codecs
Signed-off-by: Kevin Pouget <kpouget at redhat.com>
---
server/main-dispatcher.c | 31 ++++++++++++++++++++++++++++++-
server/main-dispatcher.h | 1 +
server/red-stream-device.c | 6 +++---
server/red-stream-device.h | 2 +-
server/reds.c | 11 +++++++++++
server/reds.h | 2 +-
server/stream-channel.c | 6 ++++++
7 files changed, 53 insertions(+), 6 deletions(-)
diff --git a/server/main-dispatcher.c b/server/main-dispatcher.c
index 2ca68a4d..04f5ac88 100644
--- a/server/main-dispatcher.c
+++ b/server/main-dispatcher.c
@@ -126,7 +126,7 @@ enum {
MAIN_DISPATCHER_MIGRATE_SEAMLESS_DST_COMPLETE,
MAIN_DISPATCHER_SET_MM_TIME_LATENCY,
MAIN_DISPATCHER_CLIENT_DISCONNECT,
-
+ MAIN_DISPATCHER_RESET_STREAM_CHANNELS,
MAIN_DISPATCHER_NUM_MESSAGES
};
@@ -148,6 +148,11 @@ typedef struct MainDispatcherClientDisconnectMessage {
RedClient *client;
} MainDispatcherClientDisconnectMessage;
+
+typedef struct MainDispatcherResetStreamChannelMessage {
+ RedClient *client;
+} MainDispatcherResetStreamChannelMessage;
+
/* channel_event - calls core->channel_event, must be done in main thread */
static void main_dispatcher_handle_channel_event(void *opaque,
void *payload)
@@ -203,6 +208,17 @@ static void main_dispatcher_handle_client_disconnect(void *opaque,
g_object_unref(msg->client);
}
+static void main_dispatcher_handle_reset_stream_channel(void *opaque,
+ void *payload)
+{
+ RedsState *reds = opaque;
+ MainDispatcherResetStreamChannelMessage __attribute__((unused)) *msg = payload;
+
+ /* TODO: reset only the char device linked to msg.client */
+
+ reds_reset_all_stream_char_devices(reds);
+}
+
void main_dispatcher_seamless_migrate_dst_complete(MainDispatcher *self,
RedClient *client)
{
@@ -247,6 +263,16 @@ void main_dispatcher_client_disconnect(MainDispatcher *self, RedClient *client)
}
}
+void main_dispatcher_reset_stream_channels(MainDispatcher *self, RedClient *client)
+{
+ MainDispatcherResetStreamChannelMessage msg;
+
+ msg.client = client;
+
+ dispatcher_send_message(DISPATCHER(self), MAIN_DISPATCHER_RESET_STREAM_CHANNELS,
+ &msg);
+}
+
/*
* FIXME:
* Reds routines shouldn't be exposed. Instead reds.c should register the callbacks,
@@ -282,6 +308,9 @@ void main_dispatcher_constructed(GObject *object)
dispatcher_register_handler(DISPATCHER(self), MAIN_DISPATCHER_CLIENT_DISCONNECT,
main_dispatcher_handle_client_disconnect,
sizeof(MainDispatcherClientDisconnectMessage), false);
+ dispatcher_register_handler(DISPATCHER(self), MAIN_DISPATCHER_RESET_STREAM_CHANNELS,
+ main_dispatcher_handle_reset_stream_channel,
+ sizeof(MainDispatcherResetStreamChannelMessage), false);
}
static void main_dispatcher_finalize(GObject *object)
diff --git a/server/main-dispatcher.h b/server/main-dispatcher.h
index e1244f83..6d5f50a0 100644
--- a/server/main-dispatcher.h
+++ b/server/main-dispatcher.h
@@ -58,6 +58,7 @@ void main_dispatcher_set_mm_time_latency(MainDispatcher *self, RedClient *client
* that triggered the client destruction.
*/
void main_dispatcher_client_disconnect(MainDispatcher *self, RedClient *client);
+void main_dispatcher_reset_stream_channels(MainDispatcher *self, RedClient *client);
MainDispatcher* main_dispatcher_new(RedsState *reds);
diff --git a/server/red-stream-device.c b/server/red-stream-device.c
index 620e581e..c551de69 100644
--- a/server/red-stream-device.c
+++ b/server/red-stream-device.c
@@ -702,8 +702,8 @@ stream_device_create_channel(StreamDevice *dev)
stream_channel_register_queue_stat_cb(stream_channel, stream_device_stream_queue_stat, dev);
}
-static void
-reset_channels(StreamDevice *dev)
+void
+stream_device_reset_channels(StreamDevice *dev)
{
if (dev->stream_channel) {
stream_channel_reset(dev->stream_channel);
@@ -763,7 +763,7 @@ stream_device_port_event(RedCharDevice *char_dev, uint8_t event)
dev->has_error = false;
dev->flow_stopped = false;
red_char_device_reset(char_dev);
- reset_channels(dev);
+ stream_device_reset_channels(dev);
// enable the device again. We re-enable it on close as otherwise we don't want to get a
// failure when we try to re-open the device as would happen if we keep it disabled
diff --git a/server/red-stream-device.h b/server/red-stream-device.h
index aa2b23a2..0f080228 100644
--- a/server/red-stream-device.h
+++ b/server/red-stream-device.h
@@ -55,7 +55,7 @@ StreamDevice *stream_device_connect(RedsState *reds, SpiceCharDeviceInstance *si
* If the channel already exists the function does nothing.
*/
void stream_device_create_channel(StreamDevice *dev);
-
+void stream_device_reset_channels(StreamDevice *dev);
const StreamDeviceDisplayInfo *stream_device_get_device_display_info(StreamDevice *dev);
/**
diff --git a/server/reds.c b/server/reds.c
index a3795ab9..9aae838d 100644
--- a/server/reds.c
+++ b/server/reds.c
@@ -3301,6 +3301,17 @@ static void reds_on_char_device_destroy(RedsState *reds,
reds->char_devices = g_list_remove(reds->char_devices, dev);
}
+void reds_reset_all_stream_char_devices(RedsState *reds)
+{
+ RedCharDevice *dev;
+
+ GLIST_FOREACH(reds->char_devices, RedCharDevice, dev) {
+ if (IS_STREAM_DEVICE(dev)) {
+ stream_device_reset_channels(STREAM_DEVICE(dev));
+ }
+ }
+}
+
static int spice_server_char_device_add_interface(SpiceServer *reds,
SpiceBaseInstance *sin)
{
diff --git a/server/reds.h b/server/reds.h
index e3355f81..ec106394 100644
--- a/server/reds.h
+++ b/server/reds.h
@@ -53,7 +53,7 @@ bool reds_config_get_playback_compression(RedsState *reds); // used by playback
void reds_send_device_display_info(RedsState *reds);
void reds_handle_agent_mouse_event(RedsState *reds, const VDAgentMouseState *mouse_state); // used by inputs_channel
-
+void reds_reset_all_stream_char_devices(RedsState *reds);
GArray* reds_get_renderers(RedsState *reds);
char *reds_get_video_codec_fullname(RedVideoCodec *codec);
diff --git a/server/stream-channel.c b/server/stream-channel.c
index e0e41895..99ce7c9a 100644
--- a/server/stream-channel.c
+++ b/server/stream-channel.c
@@ -465,6 +465,12 @@ stream_channel_handle_preferred_video_codec_type(RedChannelClient *rcc,
g_clear_pointer(&scc->client_preferred_video_codecs, g_array_unref);
scc->client_preferred_video_codecs = video_stream_parse_preferred_codecs(msg);
+ /* Reset video streams */
+ RedClient *client = red_channel_client_get_client(rcc);
+ RedsState *reds = red_client_get_server(client);
+
+ main_dispatcher_reset_stream_channels(reds_get_main_dispatcher(reds), client);
+
return TRUE;
}
--
2.21.0
More information about the Spice-devel
mailing list