mirror of
https://gitlab.uni-freiburg.de/opensourcevdi/spice
synced 2026-01-03 15:58:43 +00:00
stream-channel: Add preferred video codec capability
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@redhat.com> Acked-by: Frediano Ziglio <fziglio@redhat.com>
This commit is contained in:
parent
84358a175e
commit
9ccf7bee7a
30
server/dcc.c
30
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);
|
||||
|
||||
@ -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);
|
||||
}
|
||||
|
||||
@ -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)
|
||||
{
|
||||
|
||||
@ -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);
|
||||
|
||||
Loading…
Reference in New Issue
Block a user