mirror of
https://gitlab.uni-freiburg.de/opensourcevdi/spice
synced 2026-08-12 19:18:11 +00:00
stream-channel: Support client connection/disconnection
When a new client is connected we must restart the stream so new clients can receive correct data without having to wait for the 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@redhat.com> Acked-by: Jonathon Jongsma <jjongsma@redhat.com>
This commit is contained in:
parent
3cf09bd5b3
commit
633e04b40c
@ -120,9 +120,33 @@ stream_channel_client_init(StreamChannelClient *client)
|
||||
client->stream_id = -1;
|
||||
}
|
||||
|
||||
static void
|
||||
request_new_stream(StreamChannel *channel, StreamMsgStartStop *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
|
||||
StreamMsgStartStop stop = { 0, };
|
||||
request_new_stream(channel, &stop);
|
||||
}
|
||||
|
||||
static StreamChannelClient*
|
||||
@ -258,18 +282,75 @@ stream_channel_new(RedsState *server, uint32_t id)
|
||||
NULL);
|
||||
}
|
||||
|
||||
#define MAX_SUPPORTED_CODECS SPICE_VIDEO_CODEC_TYPE_ENUM_END
|
||||
|
||||
// find common codecs supported by all clients
|
||||
static uint8_t
|
||||
stream_channel_get_supported_codecs(StreamChannel *channel, uint8_t *out_codecs)
|
||||
{
|
||||
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,
|
||||
};
|
||||
|
||||
bool supported[SPICE_N_ELEMENTS(codec2cap)];
|
||||
|
||||
for (codec = 0; codec < SPICE_N_ELEMENTS(codec2cap); ++codec) {
|
||||
supported[codec] = true;
|
||||
}
|
||||
|
||||
FOREACH_CLIENT(channel, 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] = false;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// 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]) {
|
||||
out_codecs[num++] = codec;
|
||||
}
|
||||
}
|
||||
|
||||
return num;
|
||||
}
|
||||
|
||||
static void
|
||||
stream_channel_connect(RedChannel *red_channel, RedClient *red_client, RedsStream *stream,
|
||||
int migration, RedChannelCapabilities *caps)
|
||||
{
|
||||
StreamChannel *channel = STREAM_CHANNEL(red_channel);
|
||||
StreamChannelClient *client;
|
||||
struct {
|
||||
StreamMsgStartStop base;
|
||||
uint8_t codecs_buffer[MAX_SUPPORTED_CODECS];
|
||||
} start_msg;
|
||||
StreamMsgStartStop *const start = &start_msg.base;
|
||||
|
||||
spice_return_if_fail(stream != NULL);
|
||||
|
||||
client = stream_channel_client_new(channel, red_client, stream, migration, caps);
|
||||
spice_return_if_fail(client != NULL);
|
||||
|
||||
// request new stream
|
||||
start->num_codecs = stream_channel_get_supported_codecs(channel, start->codecs);
|
||||
// send in any case, even if list is not changed
|
||||
// notify device about changes
|
||||
request_new_stream(channel, start);
|
||||
|
||||
|
||||
// TODO set capabilities like SPICE_DISPLAY_CAP_MONITORS_CONFIG
|
||||
// see guest_set_client_capabilities
|
||||
RedChannelClient *rcc = RED_CHANNEL_CLIENT(client);
|
||||
|
||||
Loading…
Reference in New Issue
Block a user