[Spice-devel] [PATCH] stream-channel: Add preferred video codec capability
Kevin Pouget
kpouget at redhat.com
Mon Sep 2 07:27:57 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>
---
This patch adds the client preferred video codecs capability, and
stores the list in the StreamChannelClient fields, but doesn't pass it
in anyway to the streaming-agent.
We can decide later on what's the right thing to do with this
list. See those RFC patches for a possibility:
> stream-channel: Use the preferred codec list instead of supported
>> https://patchwork.freedesktop.org/patch/322039/?series=64787&rev=3
> streaming: Restart guest video streams on video-codec changes
>> https://patchwork.freedesktop.org/patch/322040/?series=64787&rev=3
---
server/dcc.c | 30 +-----------------------------
server/stream-channel.c | 39 +++++++++++++++++++++++++++++++++++++++
server/video-stream.c | 35 +++++++++++++++++++++++++++++++++++
server/video-stream.h | 1 +
4 files changed, 76 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..7448f21e 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"
#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;
};
struct StreamChannelClientClass {
@@ -114,15 +118,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 +343,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 +412,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 *scc = STREAM_CHANNEL_CLIENT(rcc);
+
+ 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;
+}
+
static void
stream_channel_connect(RedChannel *red_channel, RedClient *red_client, RedStream *stream,
int migration, RedChannelCapabilities *caps)
@@ -448,6 +486,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
More information about the Spice-devel
mailing list