This patch enables the SPICE_DISPLAY_CAP_PREF_VIDEO_CODEC_TYPE capability for the stream-channel. video_stream_parse_preferred_codecs: new function for parsing the SPICE protocol message. This code used to in inside dcc_handle_preferred_video_codec_type. struct StreamChannelClient::client_preferred_video_codecs: new field. Signed-off-by: Kevin Pouget <kpouget@xxxxxxxxxx> --- v1->v2: - removed extra header (red-client.h) - s/scc/client --- server/dcc.c | 30 +----------------------------- server/stream-channel.c | 38 ++++++++++++++++++++++++++++++++++++++ server/video-stream.c | 35 +++++++++++++++++++++++++++++++++++ server/video-stream.h | 1 + 4 files changed, 75 insertions(+), 29 deletions(-) diff --git a/server/dcc.c b/server/dcc.c index 21e8598e..538f1f51 100644 --- a/server/dcc.c +++ b/server/dcc.c @@ -1158,38 +1158,10 @@ static void on_display_video_codecs_update(GObject *gobject, GParamSpec *pspec, static int dcc_handle_preferred_video_codec_type(DisplayChannelClient *dcc, SpiceMsgcDisplayPreferredVideoCodecType *msg) { - gint i, len; - gint indexes[SPICE_VIDEO_CODEC_TYPE_ENUM_END]; - GArray *client; - g_return_val_if_fail(msg->num_of_codecs > 0, TRUE); - /* set default to a big and positive number */ - memset(indexes, 0x7f, sizeof(indexes)); - - for (len = 0, i = 0; i < msg->num_of_codecs; i++) { - gint video_codec = msg->codecs[i]; - - if (video_codec < SPICE_VIDEO_CODEC_TYPE_MJPEG || - video_codec >= SPICE_VIDEO_CODEC_TYPE_ENUM_END) { - spice_debug("Client has sent unknown video-codec (value %d at index %d). " - "Ignoring as server can't handle it", - video_codec, i); - continue; - } - - if (indexes[video_codec] < SPICE_VIDEO_CODEC_TYPE_ENUM_END) { - continue; - } - - len++; - indexes[video_codec] = len; - } - client = g_array_sized_new(FALSE, FALSE, sizeof(gint), SPICE_VIDEO_CODEC_TYPE_ENUM_END); - g_array_append_vals(client, indexes, SPICE_VIDEO_CODEC_TYPE_ENUM_END); - g_clear_pointer(&dcc->priv->client_preferred_video_codecs, g_array_unref); - dcc->priv->client_preferred_video_codecs = client; + dcc->priv->client_preferred_video_codecs = video_stream_parse_preferred_codecs(msg); /* New client preference */ dcc_update_preferred_video_codecs(dcc); diff --git a/server/stream-channel.c b/server/stream-channel.c index 7953018e..cc0eae5d 100644 --- a/server/stream-channel.c +++ b/server/stream-channel.c @@ -52,6 +52,9 @@ struct StreamChannelClient { /* current video stream id, <0 if not initialized or * we are not sending a stream */ int stream_id; + /* Array with SPICE_VIDEO_CODEC_TYPE_ENUM_END elements, with the client + * preference order (index) as value */ + GArray *client_preferred_video_codecs; }; struct StreamChannelClientClass { @@ -114,15 +117,30 @@ typedef struct StreamDataItem { #define PRIMARY_SURFACE_ID 0 static void stream_channel_client_on_disconnect(RedChannelClient *rcc); +static bool +stream_channel_handle_preferred_video_codec_type(RedChannelClient *rcc, + SpiceMsgcDisplayPreferredVideoCodecType *msg); RECORDER(stream_channel_data, 32, "Stream channel data packet"); +static void +stream_channel_client_finalize(GObject *object) +{ + StreamChannelClient *self = STREAM_CHANNEL_CLIENT(object); + g_clear_pointer(&self->client_preferred_video_codecs, g_array_unref); + + G_OBJECT_CLASS(stream_channel_client_parent_class)->finalize(object); +} + static void stream_channel_client_class_init(StreamChannelClientClass *klass) { + GObjectClass *object_class = G_OBJECT_CLASS(klass); + RedChannelClientClass *channel_class = RED_CHANNEL_CLIENT_CLASS(klass); channel_class->on_disconnect = stream_channel_client_on_disconnect; + object_class->finalize = stream_channel_client_finalize; } static void @@ -324,6 +342,9 @@ handle_message(RedChannelClient *rcc, uint16_t type, uint32_t size, void *msg) case SPICE_MSGC_DISPLAY_GL_DRAW_DONE: /* client should not send this message */ return false; + case SPICE_MSGC_DISPLAY_PREFERRED_VIDEO_CODEC_TYPE: + return stream_channel_handle_preferred_video_codec_type(rcc, + (SpiceMsgcDisplayPreferredVideoCodecType *)msg); default: return red_channel_client_handle_message(rcc, type, size, msg); } @@ -390,6 +411,22 @@ stream_channel_get_supported_codecs(StreamChannel *channel, uint8_t *out_codecs) return num; } +static bool +stream_channel_handle_preferred_video_codec_type(RedChannelClient *rcc, + SpiceMsgcDisplayPreferredVideoCodecType *msg) +{ + StreamChannelClient *client = STREAM_CHANNEL_CLIENT(rcc); + + if (msg->num_of_codecs == 0) { + return true; + } + + g_clear_pointer(&client->client_preferred_video_codecs, g_array_unref); + client->client_preferred_video_codecs = video_stream_parse_preferred_codecs(msg); + + return true; +} + static void stream_channel_connect(RedChannel *red_channel, RedClient *red_client, RedStream *stream, int migration, RedChannelCapabilities *caps) @@ -448,6 +485,7 @@ stream_channel_constructed(GObject *object) red_channel_set_cap(red_channel, SPICE_DISPLAY_CAP_MONITORS_CONFIG); red_channel_set_cap(red_channel, SPICE_DISPLAY_CAP_STREAM_REPORT); + red_channel_set_cap(red_channel, SPICE_DISPLAY_CAP_PREF_VIDEO_CODEC_TYPE); reds_register_channel(reds, red_channel); } diff --git a/server/video-stream.c b/server/video-stream.c index 6aa859a0..6714d780 100644 --- a/server/video-stream.c +++ b/server/video-stream.c @@ -468,6 +468,41 @@ static bool video_stream_add_frame(DisplayChannel *display, return FALSE; } +/* Returns an array with SPICE_VIDEO_CODEC_TYPE_ENUM_END elements, + * with the client preference order (index) as value */ +GArray *video_stream_parse_preferred_codecs(SpiceMsgcDisplayPreferredVideoCodecType *msg) +{ + int i, len; + int indexes[SPICE_VIDEO_CODEC_TYPE_ENUM_END]; + GArray *client; + + /* set default to a big and positive number */ + memset(indexes, 0x7f, sizeof(indexes)); + + for (len = 0, i = 0; i < msg->num_of_codecs; i++) { + SpiceVideoCodecType video_codec = msg->codecs[i]; + + if (video_codec < SPICE_VIDEO_CODEC_TYPE_MJPEG || + video_codec >= SPICE_VIDEO_CODEC_TYPE_ENUM_END) { + spice_debug("Client has sent unknown video-codec (value %d at index %d). " + "Ignoring as server can't handle it", + video_codec, i); + continue; + } + + if (indexes[video_codec] < SPICE_VIDEO_CODEC_TYPE_ENUM_END) { + continue; + } + + len++; + indexes[video_codec] = len; + } + client = g_array_sized_new(FALSE, FALSE, sizeof(int), SPICE_VIDEO_CODEC_TYPE_ENUM_END); + g_array_append_vals(client, indexes, SPICE_VIDEO_CODEC_TYPE_ENUM_END); + + return client; +} + /* TODO: document the difference between the 2 functions below */ void video_stream_trace_update(DisplayChannel *display, Drawable *drawable) { diff --git a/server/video-stream.h b/server/video-stream.h index 46b076fd..73435515 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); +GArray *video_stream_parse_preferred_codecs(SpiceMsgcDisplayPreferredVideoCodecType *msg); 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