Hello, On Wed, Aug 14, 2019 at 3:08 PM Frediano Ziglio <fziglio@xxxxxxxxxx> wrote: > > > > > 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 be inside > > dcc_handle_preferred_video_codec_type. > > > > struct StreamChannelClient::client_preferred_video_codecs: new field. > > > > Signed-off-by: Kevin Pouget <kpouget@xxxxxxxxxx> > > --- > > server/dcc.c | 30 +----------------------------- > > server/stream-channel.c | 40 ++++++++++++++++++++++++++++++++++++++++ > > server/video-stream.c | 36 ++++++++++++++++++++++++++++++++++++ > > server/video-stream.h | 1 + > > 4 files changed, 78 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..fa4804f1 100644 > > --- a/server/stream-channel.c > > +++ b/server/stream-channel.c > > @@ -22,6 +22,7 @@ > > #include <spice/stream-device.h> > > > > #include "red-channel-client.h" > > +#include "red-client.h" > > Why red-client ?? Should not be video-stream.h ? this include allows me to convert this "reds = red_client_get_server(client)" > stream_channel_handle_preferred_video_codec_type(RedChannelClient *rcc, ...) { > RedClient *client = red_channel_client_get_client(rcc); > RedsState *reds = red_client_get_server(client); > main_dispatcher_reset_stream_channel(reds_get_main_dispatcher(reds), channel_id); > > #include "stream-channel.h" > > #include "reds.h" > > #include "common-graphics-channel.h" > > @@ -52,6 +53,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; > > I think that currently a static array takes less space, but it's just my > paranoia. you mean to change the type to "SpiceVideoCodecType __name__[SPICE_VIDEO_CODEC_TYPE_ENUM_END]"? yes, could be, but I think what ever we change on this side, we should change it on host-encoding side, for consistency. I'm not sure it's worth the effort for saving a few bytes of glib wrapper? > > }; > > > > struct StreamChannelClientClass { > > @@ -114,6 +118,8 @@ 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); > > > > Minor: Not correctly indented this was on purpose, as the "correct" alignment of 'msg' would go > 100chars I put a new line between "<return type> <function name>" > > RECORDER(stream_channel_data, 32, "Stream channel data packet"); > > > > @@ -324,6 +330,10 @@ 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); > > + return false; > > Second return after a return is not much useful, some code analysers > could also complain about it. yes, this is fully useless, I cancelled the second return > > default: > > return red_channel_client_handle_message(rcc, type, size, msg); > > } > > @@ -390,6 +400,20 @@ 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 *scc = STREAM_CHANNEL_CLIENT(rcc); > > + > > + g_return_val_if_fail(msg->num_of_codecs > 0, TRUE); > > I know it's not a regression, but document for g_return_val_if_fail states > "Verifies that the expression expr , usually representing a precondition, evaluates to TRUE" > but this is not a precondition, this is checking a value from network. I don't know, it actually looks like a precondition to me, even if it's a RPC call. but the type of num_of_codecs is uint8_t, so >=0. I can replace this with > if (msg->num_of_codecs == 0) { > return true; > } > > + > > + g_clear_pointer(&scc->client_preferred_video_codecs, g_array_unref); > > + scc->client_preferred_video_codecs = > > video_stream_parse_preferred_codecs(msg); > > + > > + return TRUE; > > I would use true/false with bool sure > > +} > > + > > static void > > stream_channel_connect(RedChannel *red_channel, RedClient *red_client, > > RedStream *stream, > > int migration, RedChannelCapabilities *caps) > > @@ -448,10 +472,25 @@ 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); > > } > > > > +static void > > +stream_channel_finalize(GObject *object) > > +{ > > + StreamChannel *self = STREAM_CHANNEL(object); > > + RedChannelClient *rcc; > > + > > + FOREACH_CLIENT(self, rcc) { > > + StreamChannelClient *scc = STREAM_CHANNEL_CLIENT(rcc); > > + g_clear_pointer(&scc->client_preferred_video_codecs, g_array_unref); > > + } > > Each object should free itself, this should be in > stream_channel_client_finalize, otherwise code will leak when client disconnects. I see, I confused myself with the channel_class vs channel_client_class. Fixed now > > + > > + G_OBJECT_CLASS(stream_channel_parent_class)->finalize(object); > > +} > > + > > static void > > stream_channel_class_init(StreamChannelClass *klass) > > { > > @@ -459,6 +498,7 @@ stream_channel_class_init(StreamChannelClass *klass) > > RedChannelClass *channel_class = RED_CHANNEL_CLASS(klass); > > > > object_class->constructed = stream_channel_constructed; > > + object_class->finalize = stream_channel_finalize; > > > > channel_class->parser = > > spice_get_client_channel_parser(SPICE_CHANNEL_DISPLAY, NULL); > > channel_class->handle_message = handle_message; > > diff --git a/server/video-stream.c b/server/video-stream.c > > index 6aa859a0..a61c8ab2 100644 > > --- a/server/video-stream.c > > +++ b/server/video-stream.c > > @@ -20,6 +20,7 @@ > > #include "display-channel-private.h" > > #include "main-channel-client.h" > > #include "red-client.h" > > +#include "stream-channel.h" > > > > Why this? removed > > #define FPS_TEST_INTERVAL 1 > > #define FOREACH_STREAMS(display, item) \ > > @@ -468,6 +469,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) > > +{ > > + gint i, len; > > gnot ga gbig gfun gof gall gthese gg gstrings fixed, this is a code moved from elsewhere, but it's worth fixing the types as glib is not involved with this variables > 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; > } --- but now, I'm not sure what to do with this Preferred Video Codec list. This patch only sets the StreamChannelClient attribute: > scc->client_preferred_video_codecs = video_stream_parse_preferred_codecs(msg); so it should be discussed in with this email: > [RFC spice-server 3/3] streaming: Restart guest video streams on video-codec changes thanks, Kevin > > + gint 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++) { > > + 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); > > + > > + 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); > > Frediano _______________________________________________ Spice-devel mailing list Spice-devel@xxxxxxxxxxxxxxxxxxxxx https://lists.freedesktop.org/mailman/listinfo/spice-devel