[Spice-devel] [spice v8 04/24] server: Check the client video codec capabilities
Francois Gouget
fgouget at codeweavers.com
Tue Jan 12 02:57:16 PST 2016
Signed-off-by: Francois Gouget <fgouget at codeweavers.com>
---
Note:
* This depends on the spice-protocol changes and thus raises the
minimum Spice protocol version to 0.12.12. Adjust as appropriate.
configure.ac | 2 +-
server/dcc.c | 5 ++++-
server/dcc.h | 2 +-
server/stream.c | 41 +++++++++++++++++++++++++++++------------
4 files changed, 35 insertions(+), 15 deletions(-)
diff --git a/configure.ac b/configure.ac
index f80178e..1f7afd5 100644
--- a/configure.ac
+++ b/configure.ac
@@ -123,7 +123,7 @@ AS_IF([test x"$have_smartcard" = "xyes"], [
AS_VAR_APPEND([SPICE_REQUIRES], [" libcacard >= 0.1.2"])
])
-SPICE_PROTOCOL_MIN_VER=0.12.10
+SPICE_PROTOCOL_MIN_VER=0.12.12
PKG_CHECK_MODULES([SPICE_PROTOCOL], [spice-protocol >= $SPICE_PROTOCOL_MIN_VER])
AC_SUBST([SPICE_PROTOCOL_MIN_VER])
diff --git a/server/dcc.c b/server/dcc.c
index 25c18d8..829f76c 100644
--- a/server/dcc.c
+++ b/server/dcc.c
@@ -407,7 +407,10 @@ static void dcc_create_all_streams(DisplayChannelClient *dcc)
while ((item = ring_next(ring, item))) {
Stream *stream = SPICE_CONTAINEROF(item, Stream, link);
- dcc_create_stream(dcc, stream);
+ if (!dcc_create_stream(dcc, stream)) {
+ stream_stop(DCC_TO_DC(dcc), stream);
+ return;
+ }
}
}
diff --git a/server/dcc.h b/server/dcc.h
index b510254..34ca346 100644
--- a/server/dcc.h
+++ b/server/dcc.h
@@ -173,7 +173,7 @@ void dcc_destroy_surface (DisplayCha
uint32_t surface_id);
void dcc_stream_agent_clip (DisplayChannelClient* dcc,
StreamAgent *agent);
-void dcc_create_stream (DisplayChannelClient *dcc,
+gboolean dcc_create_stream (DisplayChannelClient *dcc,
Stream *stream);
void dcc_create_surface (DisplayChannelClient *dcc,
int surface_id);
diff --git a/server/stream.c b/server/stream.c
index 9c335b6..bbc7003 100644
--- a/server/stream.c
+++ b/server/stream.c
@@ -440,7 +440,12 @@ static void display_channel_create_stream(DisplayChannel *display, Drawable *dra
display->streams_size_total += stream->width * stream->height;
display->stream_count++;
FOREACH_DCC(display, dcc_ring_item, next, dcc) {
- dcc_create_stream(dcc, stream);
+ if (!dcc_create_stream(dcc, stream)) {
+ drawable->stream = NULL;
+ stream->current = NULL;
+ stream_stop(display, stream);
+ return;
+ }
}
spice_debug("stream %d %dx%d (%d, %d) (%d, %d) %u fps",
(int)(stream - display->streams_buf), stream->width,
@@ -695,25 +700,32 @@ 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,
void *cbs_opaque)
{
+ 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, cbs_opaque);
- if (video_encoder) {
- return video_encoder;
- }
+ VideoEncoder* video_encoder = gstreamer_encoder_new(starting_bit_rate, cbs, cbs_opaque);
+ if (video_encoder) {
+ return video_encoder;
+ }
#endif
- /* Use the builtin MJPEG video encoder as a fallback */
- return mjpeg_encoder_new(starting_bit_rate, cbs, cbs_opaque);
+ /* Use the builtin MJPEG video encoder as a fallback */
+ return mjpeg_encoder_new(starting_bit_rate, cbs, cbs_opaque);
+ }
+
+ return NULL;
}
-void dcc_create_stream(DisplayChannelClient *dcc, Stream *stream)
+gboolean dcc_create_stream(DisplayChannelClient *dcc, Stream *stream)
{
StreamAgent *agent = &dcc->stream_agents[get_stream_id(DCC_TO_DC(dcc), stream)];
- spice_return_if_fail(region_is_empty(&agent->vis_region));
+ spice_return_val_if_fail(region_is_empty(&agent->vis_region), FALSE);
stream->refs++;
if (stream->current) {
@@ -736,9 +748,13 @@ 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);
+ agent->video_encoder = dcc_create_video_encoder(dcc, initial_bit_rate, &video_cbs, agent);
} else {
- agent->video_encoder = dcc_create_video_encoder(0, NULL, NULL);
+ agent->video_encoder = dcc_create_video_encoder(dcc, 0, NULL, NULL);
+ }
+ if (agent->video_encoder == NULL) {
+ stream->refs--;
+ return FALSE;
}
red_channel_client_pipe_add(RED_CHANNEL_CLIENT(dcc), &agent->create_item);
@@ -757,6 +773,7 @@ void dcc_create_stream(DisplayChannelClient *dcc, Stream *stream)
agent->stats.start = stream->current->red_drawable->mm_time;
}
#endif
+ return TRUE;
}
void stream_agent_stop(StreamAgent *agent)
--
2.6.4
More information about the Spice-devel
mailing list