This patch resets (stream_channel_reset) the guest video streams when the the user changes the preferred video-codecs or when the host admin updates the list of video-codecs allowed. See also patch 4000846c0157a787b786a9bf7f36f0b6a73dfbf8 for the host streaming counter part. --- server/dcc.c | 4 +++- server/display-channel.c | 2 +- server/red-stream-device.c | 15 +++++++++++++++ server/red-stream-device.h | 1 + server/reds.c | 11 +++++++++++ server/reds.h | 1 + server/stream-channel.c | 34 ++++++++++++++++++++++++++++++---- server/video-stream.c | 8 ++++++++ server/video-stream.h | 1 + 9 files changed, 71 insertions(+), 6 deletions(-) diff --git a/server/dcc.c b/server/dcc.c index 21e8598e..2113d394 100644 --- a/server/dcc.c +++ b/server/dcc.c @@ -22,6 +22,7 @@ #include "display-channel.h" #include "display-channel-private.h" #include "red-client.h" +#include "red-stream-device.h" #include "main-channel-client.h" #include <spice-server-enums.h> #include "glib-compat.h" @@ -1193,7 +1194,8 @@ static int dcc_handle_preferred_video_codec_type(DisplayChannelClient *dcc, /* New client preference */ dcc_update_preferred_video_codecs(dcc); - video_stream_detach_and_stop(DCC_TO_DC(dcc)); + + video_stream_codecs_changed(DCC_TO_DC(dcc)); return TRUE; } diff --git a/server/display-channel.c b/server/display-channel.c index 75266598..65bc15ca 100644 --- a/server/display-channel.c +++ b/server/display-channel.c @@ -256,7 +256,7 @@ void display_channel_set_video_codecs(DisplayChannel *display, GArray *video_cod display->priv->video_codecs = g_array_ref(video_codecs); g_object_notify(G_OBJECT(display), "video-codecs"); - video_stream_detach_and_stop(display); + video_stream_codecs_changed(display); } GArray *display_channel_get_video_codecs(DisplayChannel *display) diff --git a/server/red-stream-device.c b/server/red-stream-device.c index 620e581e..1208a395 100644 --- a/server/red-stream-device.c +++ b/server/red-stream-device.c @@ -710,6 +710,21 @@ reset_channels(StreamDevice *dev) } } +void +stream_device_codecs_changed(RedCharDevice *char_dev) +{ + StreamDevice *dev = STREAM_DEVICE(char_dev); + + StreamChannel *channel = dev->stream_channel; + + if (channel == NULL) { + return; + } + + /* interrupt the guest-side video streams*/ + stream_channel_reset(channel); +} + static void char_device_set_state(RedCharDevice *char_dev, int state) { diff --git a/server/red-stream-device.h b/server/red-stream-device.h index aa2b23a2..c48182e4 100644 --- a/server/red-stream-device.h +++ b/server/red-stream-device.h @@ -55,6 +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_codecs_changed(RedCharDevice *char_dev); const StreamDeviceDisplayInfo *stream_device_get_device_display_info(StreamDevice *dev); diff --git a/server/reds.c b/server/reds.c index 78bbe5a0..d15e11b3 100644 --- a/server/reds.c +++ b/server/reds.c @@ -1880,6 +1880,17 @@ static void reds_late_initialization(RedsState *reds) reds->late_initialization_done = true; } +void +reds_codecs_changed(RedsState *reds) { + RedCharDevice *dev; + + GLIST_FOREACH(reds->char_devices, RedCharDevice, dev) { + if (IS_STREAM_DEVICE(dev)) { + stream_device_codecs_changed(dev); + } + } +} + static void red_channel_capabilities_init_from_link_message(RedChannelCapabilities *caps, const SpiceLinkMess *link_mess) diff --git a/server/reds.h b/server/reds.h index e3355f81..40feb330 100644 --- a/server/reds.h +++ b/server/reds.h @@ -92,6 +92,7 @@ int reds_on_migrate_dst_set_seamless(RedsState *reds, MainChannelClient *mcc, ui void reds_on_client_semi_seamless_migrate_complete(RedsState *reds, RedClient *client); void reds_on_client_seamless_migrate_complete(RedsState *reds, RedClient *client); void reds_on_main_channel_migrate(RedsState *reds, MainChannelClient *mcc); +void reds_codecs_changed(RedsState *reds); void reds_set_client_mm_time_latency(RedsState *reds, RedClient *client, uint32_t latency); uint32_t reds_get_streaming_video(const RedsState *reds); diff --git a/server/stream-channel.c b/server/stream-channel.c index 7953018e..35441ebf 100644 --- a/server/stream-channel.c +++ b/server/stream-channel.c @@ -369,17 +369,38 @@ stream_channel_get_supported_codecs(StreamChannel *channel, uint8_t *out_codecs) } FOREACH_CLIENT(channel, rcc) { + RedChannel *red_channel = red_channel_client_get_channel(rcc); + RedsState *reds = red_channel_get_server(red_channel); + GArray *preferred_codecs = reds_get_video_codecs(reds); + for (codec = 1; codec < SPICE_N_ELEMENTS(codec2cap); ++codec) { - // if do not support codec delete from list + // skip the codec if it is already not supported + if (!supported[codec]) { + continue; + } + + // delete the codec from list if it's not supported if (!red_channel_client_test_remote_cap(rcc, codec2cap[codec])) { supported[codec] = false; + continue; + } + + // delete the codec from list if it's not in the preferred list + bool preferred_has_codec = false; + int i; + + for (i = 0; i < preferred_codecs->len; i++) { + RedVideoCodec pref_codec = g_array_index(preferred_codecs, RedVideoCodec, i); + + if (pref_codec.type == codec) { + preferred_has_codec = true; + break; + } } + supported[codec] = preferred_has_codec; } } - // surely mjpeg is supported - supported[SPICE_VIDEO_CODEC_TYPE_MJPEG] = true; - int num = 0; for (codec = 1; codec < SPICE_N_ELEMENTS(codec2cap); ++codec) { if (supported[codec]) { @@ -387,6 +408,11 @@ stream_channel_get_supported_codecs(StreamChannel *channel, uint8_t *out_codecs) } } + if (num == 0) { + // surely mjpeg is supported + supported[SPICE_VIDEO_CODEC_TYPE_MJPEG] = true; + } + return num; } diff --git a/server/video-stream.c b/server/video-stream.c index 6aa859a0..483c42f1 100644 --- a/server/video-stream.c +++ b/server/video-stream.c @@ -950,6 +950,14 @@ void video_stream_timeout(DisplayChannel *display) } } +void video_stream_codecs_changed(DisplayChannel *display) { + /* interrupt the guest-side video streams*/ + reds_codecs_changed(red_channel_get_server(RED_CHANNEL(display))); + + /* interrupt the server-side video streams*/ + video_stream_detach_and_stop(display); +} + void video_stream_trace_add_drawable(DisplayChannel *display, Drawable *item) { diff --git a/server/video-stream.h b/server/video-stream.h index 46b076fd..fe74fc34 100644 --- a/server/video-stream.h +++ b/server/video-stream.h @@ -147,6 +147,7 @@ void video_stream_detach_and_stop(DisplayChannel *display); void video_stream_trace_add_drawable(DisplayChannel *display, Drawable *item); void video_stream_detach_behind(DisplayChannel *display, QRegion *region, Drawable *drawable); +void video_stream_codecs_changed(DisplayChannel *display); void video_stream_agent_unref(DisplayChannel *display, VideoStreamAgent *agent); void video_stream_agent_stop(VideoStreamAgent *agent); -- 2.21.0 _______________________________________________ Spice-devel mailing list Spice-devel@xxxxxxxxxxxxxxxxxxxxx https://lists.freedesktop.org/mailman/listinfo/spice-devel