[Spice-devel] [PATCH spice-server v2] stream-channel: Add preferred video codec capability

Frediano Ziglio fziglio at redhat.com
Mon Sep 2 08:55:31 UTC 2019


> 
> 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 at redhat.com>

Acked

> ---
> 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);


More information about the Spice-devel mailing list