[Spice-devel] [spice v1 10/10] dcc: handle preferred video codec message

Victor Toso victortoso at redhat.com
Mon Oct 24 13:29:03 UTC 2016


From: Victor Toso <me at victortoso.com>

SPICE_MSGC_DISPLAY_PREFERRED_VIDEO_CODEC_TYPE can be used to set the
preferred order of video codecs to be used based in client's
preference.

A new function is introduced in reds.c to update its video codec:
reds_set_video_codecs_from_client_preferred_msg() - it only update the
rank values of existing video codecs.

It is important to note that this message will not _immediately_
change a ongoing streaming; It might change the video codec on newly
created streams.

Signed-off-by: Victor Toso <victortoso at redhat.com>
---
 server/dcc.c        | 13 +++++++++++++
 server/red-worker.c |  1 +
 server/reds.c       | 35 +++++++++++++++++++++++++++++++++++
 server/reds.h       |  3 +++
 4 files changed, 52 insertions(+)

diff --git a/server/dcc.c b/server/dcc.c
index 5c05c3b..c86f8db 100644
--- a/server/dcc.c
+++ b/server/dcc.c
@@ -1097,6 +1097,16 @@ static int dcc_handle_preferred_compression(DisplayChannelClient *dcc,
     return TRUE;
 }
 
+static int dcc_handle_preferred_video_codec_type(DisplayChannelClient *dcc,
+         SpiceMsgcDisplayPreferredVideoCodecType *msg)
+{
+    RedsState *reds;
+
+    reds = red_channel_get_server(red_channel_client_get_channel(&dcc->parent));
+    reds_set_video_codecs_from_client_preferred_msg(reds, msg->codec_ranks, msg->num_of_codecs);
+    return TRUE;
+}
+
 static int dcc_handle_gl_draw_done(DisplayChannelClient *dcc)
 {
     DisplayChannel *display = DCC_TO_DC(dcc);
@@ -1127,6 +1137,9 @@ int dcc_handle_message(RedChannelClient *rcc, uint32_t size, uint16_t type, void
             (SpiceMsgcDisplayPreferredCompression *)msg);
     case SPICE_MSGC_DISPLAY_GL_DRAW_DONE:
         return dcc_handle_gl_draw_done(dcc);
+    case SPICE_MSGC_DISPLAY_PREFERRED_VIDEO_CODEC_TYPE:
+        return dcc_handle_preferred_video_codec_type(dcc,
+            (SpiceMsgcDisplayPreferredVideoCodecType *)msg);
     default:
         return red_channel_client_handle_message(rcc, size, type, msg);
     }
diff --git a/server/red-worker.c b/server/red-worker.c
index 40e58f2..8e8be5b 100644
--- a/server/red-worker.c
+++ b/server/red-worker.c
@@ -1384,6 +1384,7 @@ RedWorker* red_worker_new(QXLInstance *qxl,
     red_channel_register_client_cbs(channel, client_display_cbs, dispatcher);
     red_channel_set_cap(channel, SPICE_DISPLAY_CAP_MONITORS_CONFIG);
     red_channel_set_cap(channel, SPICE_DISPLAY_CAP_PREF_COMPRESSION);
+    red_channel_set_cap(channel, SPICE_DISPLAY_CAP_PREF_VIDEO_CODEC_TYPE);
     red_channel_set_cap(channel, SPICE_DISPLAY_CAP_STREAM_REPORT);
     reds_register_channel(reds, channel);
 
diff --git a/server/reds.c b/server/reds.c
index 6dbc010..28acddd 100644
--- a/server/reds.c
+++ b/server/reds.c
@@ -3649,6 +3649,41 @@ static void reds_set_video_codecs(RedsState *reds, GArray *video_codecs)
     reds->config->video_codecs = video_codecs;
 }
 
+void reds_set_video_codecs_from_client_preferred_msg(RedsState *reds,
+        SpiceVideoCodecPreferredRank *codec_ranks, guint32 codec_ranks_len)
+{
+    gint i;
+    GArray *video_codecs;
+
+    /* Dup the current array */
+    video_codecs = g_array_new(FALSE, FALSE, sizeof(RedVideoCodec));
+    for (i = 0; i < reds->config->video_codecs->len; i++) {
+        RedVideoCodec codec = g_array_index(reds->config->video_codecs, RedVideoCodec, i);
+
+        /* Only one type of codec should be set as preferred - reset to sofware decoder */
+        if (codec.rank == SPICE_VIDEO_CODEC_RANK_PREFERRED)
+            codec.rank = SPICE_VIDEO_CODEC_RANK_SOFTWARE_DECODER;
+
+        g_array_append_val(video_codecs, codec);
+    }
+
+    /* Update the rank based in the information given by client */
+    for (i = 0; i < codec_ranks_len; i++) {
+        gint j;
+
+        for (j = 0; j < video_codecs->len; j++) {
+            RedVideoCodec *codec = &g_array_index(video_codecs, RedVideoCodec, j);
+
+            if (codec_ranks[i].type != codec->type)
+                continue;
+
+            codec->rank = codec_ranks[i].rank;
+        }
+    }
+    reds_set_video_codecs(reds, video_codecs);
+    reds_on_vc_change(reds);
+}
+
 static void reds_set_video_codecs_from_string(RedsState *reds, const char *codecs)
 {
     char *encoder_name, *codec_name, *codec_rank;
diff --git a/server/reds.h b/server/reds.h
index cd62fc1..e3afe42 100644
--- a/server/reds.h
+++ b/server/reds.h
@@ -94,6 +94,9 @@ void reds_on_main_channel_migrate(RedsState *reds, MainChannelClient *mcc);
 void reds_set_client_mm_time_latency(RedsState *reds, RedClient *client, uint32_t latency);
 uint32_t reds_get_streaming_video(const RedsState *reds);
 GArray* reds_get_video_codecs(const RedsState *reds);
+void reds_set_video_codecs_from_client_preferred_msg(RedsState *reds,
+                                                     SpiceVideoCodecPreferredRank *codec_ranks,
+                                                     guint32 codec_ranks_len);
 spice_wan_compression_t reds_get_jpeg_state(const RedsState *reds);
 spice_wan_compression_t reds_get_zlib_glz_state(const RedsState *reds);
 SpiceCoreInterfaceInternal* reds_get_core_interface(RedsState *reds);
-- 
2.9.3



More information about the Spice-devel mailing list