[Spice-devel] [spice v14 04/29] server: Check the client video codec capabilities

Francois Gouget fgouget at codeweavers.com
Wed May 4 09:41:18 UTC 2016


The server picks a codec supported by the client based on the following
new client capabilities:
 * SPICE_DISPLAY_CAP_MULTI_CODEC which denotes a recent client that
   supports multiple codecs. This capability is needed to not have to
   hardcode that MJPEG is supported. This makes it possible to write
   clients that don't support MJPEG.
 * SPICE_DISPLAY_CAP_CODEC_XXX, where XXX is a supported codec. Note
   that for now the server only supports the MJPEG codec.

Signed-off-by: Francois Gouget <fgouget at codeweavers.com>
---
 server/dcc-send.c |  3 ++-
 server/stream.c   | 25 ++++++++++++++++---------
 2 files changed, 18 insertions(+), 10 deletions(-)

diff --git a/server/dcc-send.c b/server/dcc-send.c
index fcec8d3..025bf48 100644
--- a/server/dcc-send.c
+++ b/server/dcc-send.c
@@ -1708,7 +1708,8 @@ static int red_marshall_stream_data(RedChannelClient *rcc,
                         drawable->red_drawable->mm_time :
                         reds_get_mm_time();
     outbuf_size = dcc->send_data.stream_outbuf_size;
-    ret = agent->video_encoder->encode_frame(agent->video_encoder,
+    ret = !agent->video_encoder ? VIDEO_ENCODER_FRAME_UNSUPPORTED :
+          agent->video_encoder->encode_frame(agent->video_encoder,
                                              frame_mm_time,
                                              &image->u.bitmap, width, height,
                                              &drawable->red_drawable->u.copy.src_area,
diff --git a/server/stream.c b/server/stream.c
index f13ac0b..9d46261 100644
--- a/server/stream.c
+++ b/server/stream.c
@@ -697,17 +697,24 @@ static void update_client_playback_delay(void *opaque, uint32_t delay_ms)
 }
 
 /* A helper for dcc_create_stream(). */
-static VideoEncoder* dcc_create_video_encoder(uint64_t starting_bit_rate,
+static VideoEncoder* dcc_create_video_encoder(DisplayChannelClient *dcc,
+                                              uint64_t starting_bit_rate,
                                               VideoEncoderRateControlCbs *cbs)
 {
+    RedChannelClient *rcc = RED_CHANNEL_CLIENT(dcc);
+    int client_has_multi_codec = red_channel_client_test_remote_cap(rcc, SPICE_DISPLAY_CAP_MULTI_CODEC);
+    if (!client_has_multi_codec || red_channel_client_test_remote_cap(rcc, SPICE_DISPLAY_CAP_CODEC_MJPEG)) {
 #ifdef HAVE_GSTREAMER_1_0
-    VideoEncoder* video_encoder = gstreamer_encoder_new(starting_bit_rate, cbs);
-    if (video_encoder) {
-        return video_encoder;
-    }
+        VideoEncoder* video_encoder = gstreamer_encoder_new(starting_bit_rate, cbs);
+        if (video_encoder) {
+            return video_encoder;
+        }
 #endif
-    /* Use the builtin MJPEG video encoder as a fallback */
-    return mjpeg_encoder_new(starting_bit_rate, cbs);
+        /* Use the builtin MJPEG video encoder as a fallback */
+        return mjpeg_encoder_new(starting_bit_rate, cbs);
+    }
+
+    return NULL;
 }
 
 void dcc_create_stream(DisplayChannelClient *dcc, Stream *stream)
@@ -738,9 +745,9 @@ void dcc_create_stream(DisplayChannelClient *dcc, Stream *stream)
         video_cbs.update_client_playback_delay = update_client_playback_delay;
 
         initial_bit_rate = get_initial_bit_rate(dcc, stream);
-        agent->video_encoder = dcc_create_video_encoder(initial_bit_rate, &video_cbs);
+        agent->video_encoder = dcc_create_video_encoder(dcc, initial_bit_rate, &video_cbs);
     } else {
-        agent->video_encoder = dcc_create_video_encoder(0, NULL);
+        agent->video_encoder = dcc_create_video_encoder(dcc, 0, NULL);
     }
     red_channel_client_pipe_add(RED_CHANNEL_CLIENT(dcc), &agent->create_item);
 
-- 
2.8.0.rc3



More information about the Spice-devel mailing list