[Spice-devel] [PATCH spice 6/11] server: Add VP8 support, a video codec preference list and compatibility checks with the Spice client.

2015-05-13 Thread Francois Gouget
 @@ void red_dispatcher_on_sv_change(void)
 }
 }
 
+void red_dispatcher_on_vc_change(void)
+{
+RedWorkerMessageSetVideoCodecs payload;
+int compression_level = calc_compression_level();
+RedDispatcher *now = dispatchers;
+while (now) {
+now-qxl-st-qif-set_compression_level(now-qxl, compression_level);
+payload.num_video_codecs = num_video_codecs;
+payload.video_codecs = video_codecs;
+dispatcher_send_message(now-dispatcher,
+RED_WORKER_MESSAGE_SET_VIDEO_CODECS,
+payload);
+now = now-next;
+}
+}
+
 void red_dispatcher_set_mouse_mode(uint32_t mode)
 {
 RedWorkerMessageSetMouseMode payload;
@@ -1084,6 +1209,8 @@ void red_dispatcher_init(QXLInstance *qxl)
 init_data.pending = red_dispatcher-pending;
 init_data.num_renderers = num_renderers;
 memcpy(init_data.renderers, renderers, sizeof(init_data.renderers));
+init_data.num_video_codecs = num_video_codecs;
+memcpy(init_data.video_codecs, video_codecs, 
sizeof(init_data.video_codecs));
 
 pthread_mutex_init(red_dispatcher-async_lock, NULL);
 init_data.image_compression = image_compression;
diff --git a/server/red_dispatcher.h b/server/red_dispatcher.h
index 907b7c7..eb3aee4 100644
--- a/server/red_dispatcher.h
+++ b/server/red_dispatcher.h
@@ -22,6 +22,7 @@
 
 struct RedChannelClient;
 struct RedDispatcher;
+typedef struct RedVideoCodec RedVideoCodec;
 typedef struct AsyncCommand AsyncCommand;
 
 void red_dispatcher_init(QXLInstance *qxl);
@@ -29,11 +30,13 @@ void red_dispatcher_init(QXLInstance *qxl);
 void red_dispatcher_set_mm_time(uint32_t);
 void red_dispatcher_on_ic_change(void);
 void red_dispatcher_on_sv_change(void);
+void red_dispatcher_on_vc_change(void);
 void red_dispatcher_set_mouse_mode(uint32_t mode);
 void red_dispatcher_on_vm_stop(void);
 void red_dispatcher_on_vm_start(void);
 int red_dispatcher_count(void);
 int red_dispatcher_add_renderer(const char *name);
+int red_dispatcher_set_video_codecs(const char* codecs);
 uint32_t red_dispatcher_qxl_ram_size(void);
 int red_dispatcher_qxl_count(void);
 void red_dispatcher_async_complete(struct RedDispatcher *, AsyncCommand *);
@@ -174,6 +177,11 @@ typedef struct RedWorkerMessageSetStreamingVideo {
 uint32_t streaming_video;
 } RedWorkerMessageSetStreamingVideo;
 
+typedef struct RedWorkerMessageSetVideoCodecs {
+uint32_t num_video_codecs;
+RedVideoCodec* video_codecs;
+} RedWorkerMessageSetVideoCodecs;
+
 typedef struct RedWorkerMessageSetMouseMode {
 uint32_t mode;
 } RedWorkerMessageSetMouseMode;
diff --git a/server/red_worker.c b/server/red_worker.c
index 19e27c5..8e94e26 100644
--- a/server/red_worker.c
+++ b/server/red_worker.c
@@ -1,6 +1,7 @@
 /* -*- Mode: C; c-basic-offset: 4; indent-tabs-mode: nil -*- */
 /*
Copyright (C) 2009 Red Hat, Inc.
+   Copyright (C) 2015 Francois Gouget
 
This library is free software; you can redistribute it and/or
modify it under the terms of the GNU Lesser General Public
@@ -994,6 +995,8 @@ typedef struct RedWorker {
 uint32_t mouse_mode;
 
 uint32_t streaming_video;
+uint32_t num_video_codecs;
+RedVideoCodec video_codecs[RED_MAX_VIDEO_CODECS];
 Stream streams_buf[NUM_STREAMS];
 Stream *free_streams;
 Ring streams;
@@ -3074,10 +3077,41 @@ static void 
red_stream_update_client_playback_latency(void *opaque, uint32_t del
 main_dispatcher_set_mm_time_latency(agent-dcc-common.base.client, 
agent-dcc-streams_max_latency);
 }
 
+static VideoEncoder* red_display_create_video_encoder(DisplayChannelClient 
*dcc, uint64_t starting_bit_rate, VideoEncoderRateControlCbs *cbs, void 
*cbs_opaque)
+{
+RedWorker* worker = dcc-common.worker;
+int i;
+int client_has_multi_codec = 
red_channel_client_test_remote_cap(dcc-common.base, 
SPICE_DISPLAY_CAP_MULTI_CODEC);
+
+for (i = 0; i  worker-num_video_codecs; i++)
+{
+RedVideoCodec* video_codec = worker-video_codecs[i];
+VideoEncoder* video_encoder;
+
+if (!client_has_multi_codec 
+video_codec-type != SPICE_VIDEO_CODEC_TYPE_MJPEG)
+/* Old clients only support MJPEG */
+continue;
+ 
+if (client_has_multi_codec  
!red_channel_client_test_remote_cap(dcc-common.base, video_codec-cap))
+/* The client is recent but does not support this codec */
+continue;
+
+video_encoder = video_codec-create(video_codec-type, 
starting_bit_rate, cbs, cbs_opaque);
+if (video_encoder)
+return video_encoder;
+}
+
+/* Try to use the builtin MJPEG video encoder as a fallback */
+if (!client_has_multi_codec || 
red_channel_client_test_remote_cap(dcc-common.base, 
SPICE_DISPLAY_CAP_CODEC_MJPEG))
+return create_mjpeg_encoder(SPICE_VIDEO_CODEC_TYPE_MJPEG, 
starting_bit_rate, cbs, cbs_opaque);
+
+return NULL;
+}
+
 static void red_display_create_stream(DisplayChannelClient *dcc, Stream

[Spice-devel] [PATCH qxl 7/11] Add SpiceVideoCodecs and $XSPICE_VIDEO_CODECS for specifying video codec preferences.

2015-05-13 Thread Francois Gouget
---
 examples/spiceqxl.xorg.conf.example |  7 +++
 src/qxl.h   |  1 +
 src/qxl_driver.c|  2 ++
 src/spiceqxl_spice_server.c | 16 
 4 files changed, 26 insertions(+)

diff --git a/examples/spiceqxl.xorg.conf.example 
b/examples/spiceqxl.xorg.conf.example
index d15f7f2..a82c2be 100644
--- a/examples/spiceqxl.xorg.conf.example
+++ b/examples/spiceqxl.xorg.conf.example
@@ -51,6 +51,13 @@ Section Device
 # defaults to filter.
 #Option SpiceStreamingVideo 
 
+# Set video codecs to use.  Provide a semicolon list of
+# codecs, in preference order.  Each codec requires an encoder
+# which can be one of spice or gstreamer, and then a codec type,
+# for instance mjpeg or vp8. The default is spice:mjpeg,
+# which uses the builtin mjpeg encoder.
+#Option SpiceVideoCodecs 
+
 # Set zlib glz wan compression. Options are auto, never, always.
 # defaults to auto.
 #Option SpiceZlibGlzWanCompression 
diff --git a/src/qxl.h b/src/qxl.h
index f46bc58..14449b8 100644
--- a/src/qxl.h
+++ b/src/qxl.h
@@ -158,6 +158,7 @@ enum {
 OPTION_SURFACE_BUFFER_SIZE,
 OPTION_COMMAND_BUFFER_SIZE,
 OPTION_SPICE_SMARTCARD_FILE,
+OPTION_SPICE_VIDEO_CODECS,
 #endif
 OPTION_COUNT,
 };
diff --git a/src/qxl_driver.c b/src/qxl_driver.c
index 942067f..88b38db 100644
--- a/src/qxl_driver.c
+++ b/src/qxl_driver.c
@@ -155,6 +155,8 @@ const OptionInfoRec DefaultOptions[] =
   CommandBufferSize,OPTV_INTEGER,
{DEFAULT_COMMAND_BUFFER_SIZE}, FALSE},
 { OPTION_SPICE_SMARTCARD_FILE,
   SpiceSmartcardFile,   OPTV_STRING,{0}, FALSE},
+{ OPTION_SPICE_VIDEO_CODECS,
+  SpiceVideoCodecs, OPTV_STRING,{0}, FALSE},
 #endif
 
 { -1, NULL, OPTV_NONE, {0}, FALSE }
diff --git a/src/spiceqxl_spice_server.c b/src/spiceqxl_spice_server.c
index 14ee752..d74b29d 100644
--- a/src/spiceqxl_spice_server.c
+++ b/src/spiceqxl_spice_server.c
@@ -173,6 +173,9 @@ void xspice_set_spice_server_options(OptionInfoPtr options)
 const char *streaming_video =
 get_str_option(options, OPTION_SPICE_STREAMING_VIDEO,
XSPICE_STREAMING_VIDEO);
+const char *video_codecs =
+get_str_option(options, OPTION_SPICE_VIDEO_CODECS,
+   XSPICE_VIDEO_CODECS);
 int agent_mouse =
 get_bool_option(options, OPTION_SPICE_AGENT_MOUSE,
 XSPICE_AGENT_MOUSE);
@@ -295,6 +298,19 @@ void xspice_set_spice_server_options(OptionInfoPtr options)
 spice_server_set_streaming_video(spice_server, streaming_video_opt);
 }
 
+if (video_codecs) {
+#if SPICE_SERVER_VERSION = 0x000c06 /* 0.12.6 */
+if (spice_server_set_video_codecs(spice_server, video_codecs))
+{
+fprintf(stderr, spice: invalid video encoder %s\n, video_codecs);
+exit(1);
+}
+#else
+fprintf(stderr, spice: video_codecs are not available (spice = 
0.12.6 required)\n);
+exit(1);
+#endif
+}
+
 spice_server_set_agent_mouse
 (spice_server, agent_mouse);
 spice_server_set_playback_compression
-- 
2.1.4
___
Spice-devel mailing list
Spice-devel@lists.freedesktop.org
http://lists.freedesktop.org/mailman/listinfo/spice-devel


[Spice-devel] [PATCH protocol 5/11] Add support for the VP8 video codec and for advertising supported video codecs.

2015-05-13 Thread Francois Gouget
Clients that support other codecs besides MJPEG should advertise the 
SPICE_DISPLAY_CAP_MULTI_CODEC capability and one SPICE_DISPLAY_CAP_CODEC_XXX 
per supported codec.
---
 spice/enums.h| 1 +
 spice/protocol.h | 3 +++
 2 files changed, 4 insertions(+)

diff --git a/spice/enums.h b/spice/enums.h
index 18e2f74..14675f9 100644
--- a/spice/enums.h
+++ b/spice/enums.h
@@ -139,6 +139,7 @@ typedef enum SpicePathFlags {
 
 typedef enum SpiceVideoCodecType {
 SPICE_VIDEO_CODEC_TYPE_MJPEG = 1,
+SPICE_VIDEO_CODEC_TYPE_VP8,
 
 SPICE_VIDEO_CODEC_TYPE_ENUM_END
 } SpiceVideoCodecType;
diff --git a/spice/protocol.h b/spice/protocol.h
index bea376c..7f0b322 100644
--- a/spice/protocol.h
+++ b/spice/protocol.h
@@ -134,6 +134,9 @@ enum {
 SPICE_DISPLAY_CAP_A8_SURFACE,
 SPICE_DISPLAY_CAP_STREAM_REPORT,
 SPICE_DISPLAY_CAP_LZ4_COMPRESSION,
+SPICE_DISPLAY_CAP_MULTI_CODEC,
+SPICE_DISPLAY_CAP_CODEC_MJPEG,
+SPICE_DISPLAY_CAP_CODEC_VP8,
 };
 
 enum {
-- 
2.1.4
___
Spice-devel mailing list
Spice-devel@lists.freedesktop.org
http://lists.freedesktop.org/mailman/listinfo/spice-devel


[Spice-devel] [PATCH 0/11] Add GStreamer and VP8 support

2015-05-13 Thread Francois Gouget

This is a followup on Jeremy White's concept patch to use GStreamer:
http://www.spinics.net/lists/spice-devel/msg10030.html

There is still a lot of work ahead but this patches series has all the 
infrastructure so we're sending it out to verify that it looks ok.

First, with this patch series:
 1. You can use the SpiceVideoCodecs option in the xorg.conf file (or
$XSPICE_VIDEO_CODECS) to set your video encoder and codec 
preferences. The default is still the builtin MJPEG encoder.

 2. You can do the same from QEmu by setting the video-codecs option.

 3. Clients can expose new display capabilities to advertise that 
they support either or both of the MJPEG and VP8 codecs. The new 
server will automatically pick a codec they support based on the 
above preference list. Older clients that don't advertise these new 
capabilities will automatically get an MJPEG stream. So old and new 
clients and servers should all be compatible.

 4. The GTK and and HTML5 clients have been updated to support both 
MJPEG and VP8.

 5. Using GStreamer as the video encoder should work well for either 
codecs as long as the stream does not hit your network connection's 
bandwidth limit. Essentially this means it should be ok on LANs and 
fast WiFi networks. This should even work with multiple clients.


There's one known issue in the framework: if the Spice server and 
clients have no codec in common, red_display_create_stream() will set 
video_encoder to NULL and that's not handled well. Currently this should 
really not happen as all clients support MJPEG and we have the builtin 
MJPEG encoder as a fallback. The root of the issue is that the 
red_display_create_stream() callers assume it will never fail. But I 
don't know how to change that yet.


The GStreamer backend still has a number of limitations:
 1. It's still based on GStreamer 0.10. I don't think moving to 1.0 
will be a problem, if anything it should help (famous last words).
For instance support for dynamically changing the bitrate appears to 
be better in 1.0.

 2. It still does not have any rate control but should work fine as long 
as the bandwidth is sufficient. The issue with rate control is that, 
at least in 0.10, GStreamer encoders don't like bitrate changes, 
need some time after each change to actually match the new bitrate, 
still tend to exceed it from time to time, and sometimes just won't 
get anywhere near it. Part of these issues are likely to be bugs in 
the current implementation and it should be possible to work around 
most others.


Feedback would be greatly appreciated.


Cheers,

-- 
Francois Gouget fgou...@codeweavers.com
___
Spice-devel mailing list
Spice-devel@lists.freedesktop.org
http://lists.freedesktop.org/mailman/listinfo/spice-devel


[Spice-devel] [PATCH spice 4/11] server: Add a GStreamer 0.10 MJPEG video encoder and use it by default.

2015-05-13 Thread Francois Gouget
The GStreamer video encoder is quite primitive and mostly meant to 
introduce, test and debug the basic infrastructure.
The main limitation is the lack of rate control: the bitrate is set at 
startup and will not react to changes in the network conditions. Still 
it should work fine on LANs.
---
 configure.ac   |  18 ++
 server/Makefile.am |   8 +
 server/gstreamer_encoder.c | 441 +
 server/red_worker.c|  11 +-
 server/video_encoder.h |  10 +-
 5 files changed, 484 insertions(+), 4 deletions(-)
 create mode 100644 server/gstreamer_encoder.c

diff --git a/configure.ac b/configure.ac
index 7a9fc4b..ae11301 100644
--- a/configure.ac
+++ b/configure.ac
@@ -91,6 +91,15 @@ if test x$enable_smartcard = xyes; then
AC_DEFINE([USE_SMARTCARD], [1], [Define if supporting smartcard proxying])
 fi
 
+AC_ARG_ENABLE(gstreamer-0.10,
+[  --enable-gstreamer-0.10   Enable GStreamer 0.10 support],,
+[enable_gstreamer_0_10=yes])
+AS_IF([test x$enable_gstreamer_0_10 != xno], [enable_gstreamer_0_10=yes])
+AM_CONDITIONAL(SUPPORT_GSTREAMER_0_10, test x$enable_gstreamer_0_10 != xno)
+if test x$enable_gstreamer_0_10 = xyes; then
+   AC_DEFINE([HAVE_GSTREAMER_0_10], [1], [Define if supporting GStreamer 0.10])
+fi
+
 AC_ARG_ENABLE(automated_tests,
 [  --enable-automated-tests Enable automated tests using spicy-screenshot 
(part of spice--gtk)],,
 [enable_automated_tests=no])
@@ -127,6 +136,13 @@ if test x$enable_smartcard = xyes; then
 AS_VAR_APPEND([SPICE_REQUIRES], [ libcacard = 0.1.2])
 fi
 
+if test x$enable_gstreamer_0_10 = xyes; then
+PKG_CHECK_MODULES(GSTREAMER_0_10, [gstreamer-0.10, gstreamer-app-0.10])
+AC_SUBST(GSTREAMER_0_10_LIBS)
+AC_SUBST(GSTREAMER_0_10_CFLAGS)
+AS_VAR_APPEND([SPICE_REQUIRES], [ gstreamer-0.10])
+fi
+
 
 PKG_CHECK_MODULES([GLIB2], [glib-2.0 = 2.22])
 AS_VAR_APPEND([SPICE_REQUIRES], [ glib-2.0 = 2.22])
@@ -359,6 +375,8 @@ echo 
 
 Smartcard:${enable_smartcard}
 
+GStreamer-0.10:   ${enable_gstreamer-0.10}
+
 SASL support: ${enable_sasl}
 
 Automated tests:  ${enable_automated_tests}
diff --git a/server/Makefile.am b/server/Makefile.am
index 36b6d45..28c4a46 100644
--- a/server/Makefile.am
+++ b/server/Makefile.am
@@ -11,6 +11,7 @@ AM_CPPFLAGS = \
$(SASL_CFLAGS)  \
$(SLIRP_CFLAGS) \
$(SMARTCARD_CFLAGS) \
+   $(GSTREAMER_0_10_CFLAGS)\
$(SSL_CFLAGS)   \
$(VISIBILITY_HIDDEN_CFLAGS) \
$(WARN_CFLAGS)  \
@@ -41,6 +42,7 @@ libspice_server_la_LIBADD =   
\
$(PIXMAN_LIBS)  \
$(SASL_LIBS)\
$(SLIRP_LIBS)   \
+   $(GSTREAMER_0_10_LIBS)  
\
$(SSL_LIBS) \
$(Z_LIBS)   \
$(SPICE_NONPKGCONFIG_LIBS)  \
@@ -138,6 +140,12 @@ libspice_server_la_SOURCES +=  \
$(NULL)
 endif
 
+if SUPPORT_GSTREAMER_0_10
+libspice_server_la_SOURCES +=  \
+   gstreamer_encoder.c \
+   $(NULL)
+endif
+
 EXTRA_DIST =   \
glz_encode_match_tmpl.c \
glz_encode_tmpl.c   \
diff --git a/server/gstreamer_encoder.c b/server/gstreamer_encoder.c
new file mode 100644
index 000..ef71b73
--- /dev/null
+++ b/server/gstreamer_encoder.c
@@ -0,0 +1,441 @@
+/* -*- Mode: C; c-basic-offset: 4; indent-tabs-mode: nil -*- */
+/*
+   Copyright (C) 2015 Jeremy White
+   Copyright (C) 2015 Francois Gouget
+
+   This library is free software; you can redistribute it and/or
+   modify it under the terms of the GNU Lesser General Public
+   License as published by the Free Software Foundation; either
+   version 2.1 of the License, or (at your option) any later version.
+
+   This library is distributed in the hope that it will be useful,
+   but WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+   Lesser General Public License for more details.
+
+   You should have received a copy of the GNU Lesser General Public
+   License along with this library; if not, see A 
HREF=http://www.gnu.org/licenses/;http://www.gnu.org/licenses//A.
+*/
+#ifdef HAVE_CONFIG_H
+#include config.h
+#endif
+
+#include gst/gst.h
+#include gst/app/gstappsrc.h
+#include gst/app/gstappsink.h
+
+#include red_common.h
+
+typedef struct GstEncoder GstEncoder;
+#define VIDEO_ENCODER_T

[Spice-devel] [PATCH spice 2/11] server: Remove the rate_control_is_active field from MJpegEncoder.

2015-05-13 Thread Francois Gouget
It is redundant with the corresponding callbacks.
---

This patch only depends on patch 1/11 and is independent from the rest 
of the series.

 server/mjpeg_encoder.c | 22 +-
 server/mjpeg_encoder.h |  2 +-
 server/red_worker.c|  4 ++--
 3 files changed, 16 insertions(+), 12 deletions(-)

diff --git a/server/mjpeg_encoder.c b/server/mjpeg_encoder.c
index 95d841f..9a41ef3 100644
--- a/server/mjpeg_encoder.c
+++ b/server/mjpeg_encoder.c
@@ -164,7 +164,6 @@ struct MJpegEncoder {
 unsigned int bytes_per_pixel; /* bytes per pixel of the input buffer */
 void (*pixel_converter)(uint8_t *src, uint8_t *dest);
 
-int rate_control_is_active;
 MJpegEncoderRateControl rate_control;
 MJpegEncoderRateControlCbs cbs;
 void *cbs_opaque;
@@ -185,21 +184,25 @@ static uint32_t get_min_required_playback_delay(uint64_t 
frame_enc_size,
 uint64_t byte_rate,
 uint32_t latency);
 
-MJpegEncoder *mjpeg_encoder_new(int bit_rate_control, uint64_t 
starting_bit_rate,
+static inline int rate_control_is_active(MJpegEncoder* encoder)
+{
+return encoder-cbs.get_roundtrip_ms != NULL;
+}
+
+MJpegEncoder *mjpeg_encoder_new(uint64_t starting_bit_rate,
 MJpegEncoderRateControlCbs *cbs, void *opaque)
 {
 MJpegEncoder *enc;
 
-spice_assert(!bit_rate_control || (cbs  cbs-get_roundtrip_ms  
cbs-get_source_fps));
+spice_assert(!cbs || (cbs  cbs-get_roundtrip_ms  
cbs-get_source_fps));
 
 enc = spice_new0(MJpegEncoder, 1);
 
 enc-first_frame = TRUE;
-enc-rate_control_is_active = bit_rate_control;
 enc-rate_control.byte_rate = starting_bit_rate / 8;
 enc-starting_bit_rate = starting_bit_rate;
 
-if (bit_rate_control) {
+if (cbs) {
 struct timespec time;
 
 clock_gettime(CLOCK_MONOTONIC, time);
@@ -211,6 +214,7 @@ MJpegEncoder *mjpeg_encoder_new(int bit_rate_control, 
uint64_t starting_bit_rate
 enc-rate_control.quality_eval_data.reason = 
MJPEG_QUALITY_EVAL_REASON_RATE_CHANGE;
 enc-rate_control.warmup_start_time = ((uint64_t) time.tv_sec) * 
10 + time.tv_nsec;
 } else {
+enc-cbs.get_roundtrip_ms = NULL;
 mjpeg_encoder_reset_quality(enc, MJPEG_LEGACY_STATIC_QUALITY_ID, 
MJPEG_MAX_FPS, 0);
 }
 
@@ -607,7 +611,7 @@ static void 
mjpeg_encoder_adjust_params_to_bit_rate(MJpegEncoder *encoder)
 uint32_t latency = 0;
 uint32_t src_fps;
 
-spice_assert(encoder-rate_control_is_active);
+spice_assert(rate_control_is_active(encoder));
 
 rate_control = encoder-rate_control;
 quality_eval = rate_control-quality_eval_data;
@@ -692,7 +696,7 @@ static void mjpeg_encoder_adjust_fps(MJpegEncoder *encoder, 
uint64_t now)
 MJpegEncoderRateControl *rate_control = encoder-rate_control;
 uint64_t adjusted_fps_time_passed;
 
-spice_assert(encoder-rate_control_is_active);
+spice_assert(rate_control_is_active(encoder));
 
 adjusted_fps_time_passed = (now - rate_control-adjusted_fps_start_time) / 
1000 / 1000;
 
@@ -734,7 +738,7 @@ int mjpeg_encoder_start_frame(MJpegEncoder *encoder, 
SpiceBitmapFmt format,
 {
 uint32_t quality;
 
-if (encoder-rate_control_is_active) {
+if (rate_control_is_active(encoder)) {
 MJpegEncoderRateControl *rate_control = encoder-rate_control;
 struct timespec time;
 uint64_t now;
@@ -1131,7 +1135,7 @@ void mjpeg_encoder_client_stream_report(MJpegEncoder 
*encoder,
 end_frame_mm_time - start_frame_mm_time,
 end_frame_delay, audio_delay);
 
-if (!encoder-rate_control_is_active) {
+if (!rate_control_is_active(encoder)) {
 spice_debug(rate control was not activated: ignoring);
 return;
 }
diff --git a/server/mjpeg_encoder.h b/server/mjpeg_encoder.h
index 741ea1c..d584b92 100644
--- a/server/mjpeg_encoder.h
+++ b/server/mjpeg_encoder.h
@@ -49,7 +49,7 @@ typedef struct MJpegEncoderStats {
 double avg_quality;
 } MJpegEncoderStats;
 
-MJpegEncoder *mjpeg_encoder_new(int bit_rate_control, uint64_t 
starting_bit_rate,
+MJpegEncoder *mjpeg_encoder_new(uint64_t starting_bit_rate,
 MJpegEncoderRateControlCbs *cbs, void *opaque);
 void mjpeg_encoder_destroy(MJpegEncoder *encoder);
 
diff --git a/server/red_worker.c b/server/red_worker.c
index 5deb30b..e0ff8e9 100644
--- a/server/red_worker.c
+++ b/server/red_worker.c
@@ -3100,9 +3100,9 @@ static void 
red_display_create_stream(DisplayChannelClient *dcc, Stream *stream)
 mjpeg_cbs.update_client_playback_delay = 
red_stream_update_client_playback_latency;
 
 initial_bit_rate = red_stream_get_initial_bit_rate(dcc, stream);
-agent-mjpeg_encoder = mjpeg_encoder_new(TRUE, initial_bit_rate, 
mjpeg_cbs, agent);
+agent-mjpeg_encoder = mjpeg_encoder_new(initial_bit_rate, mjpeg_cbs, 
agent);
 } else {
-agent-mjpeg_encoder = 

[Spice-devel] [PATCH spice 1/11] server: Convert a couple of rate control checks into asserts in the mjpeg video encoder.

2015-05-13 Thread Francois Gouget
The checks would lead the reader to think these functions can be called 
when bit rate control is off when in fact they are only called when it 
is active.
---

This patch makes sense independently from the rest of the series.

 server/mjpeg_encoder.c | 9 +++--
 1 file changed, 3 insertions(+), 6 deletions(-)

diff --git a/server/mjpeg_encoder.c b/server/mjpeg_encoder.c
index 12447da..95d841f 100644
--- a/server/mjpeg_encoder.c
+++ b/server/mjpeg_encoder.c
@@ -607,9 +607,7 @@ static void 
mjpeg_encoder_adjust_params_to_bit_rate(MJpegEncoder *encoder)
 uint32_t latency = 0;
 uint32_t src_fps;
 
-if (!encoder-rate_control_is_active) {
-return;
-}
+spice_assert(encoder-rate_control_is_active);
 
 rate_control = encoder-rate_control;
 quality_eval = rate_control-quality_eval_data;
@@ -694,9 +692,8 @@ static void mjpeg_encoder_adjust_fps(MJpegEncoder *encoder, 
uint64_t now)
 MJpegEncoderRateControl *rate_control = encoder-rate_control;
 uint64_t adjusted_fps_time_passed;
 
-if (!encoder-rate_control_is_active) {
-return;
-}
+spice_assert(encoder-rate_control_is_active);
+
 adjusted_fps_time_passed = (now - rate_control-adjusted_fps_start_time) / 
1000 / 1000;
 
 if (!rate_control-during_quality_eval 
-- 
2.1.4

___
Spice-devel mailing list
Spice-devel@lists.freedesktop.org
http://lists.freedesktop.org/mailman/listinfo/spice-devel


[Spice-devel] [PATCH spice 3/11] server: Refactor the Spice server video encoding so alternative implementations can be added.

2015-05-13 Thread Francois Gouget
 :
 reds_get_mm_time();
+
 outbuf_size = dcc-send_data.stream_outbuf_size;
-ret = mjpeg_encoder_start_frame(agent-mjpeg_encoder, 
image-u.bitmap.format,
-width, height,
-dcc-send_data.stream_outbuf,
-outbuf_size,
-frame_mm_time);
+ret = agent-video_encoder-encode_frame(agent-video_encoder,
+image-u.bitmap, width, height,
+drawable-red_drawable-u.copy.src_area,
+stream-top_down, frame_mm_time,
+dcc-send_data.stream_outbuf, outbuf_size, n);
+
 switch (ret) {
-case MJPEG_ENCODER_FRAME_DROP:
-spice_assert(dcc-use_mjpeg_encoder_rate_control);
+case VIDEO_ENCODER_FRAME_DROP:
+spice_assert(dcc-use_video_encoder_rate_control);
 #ifdef STREAM_STATS
 agent-stats.num_drops_fps++;
 #endif
 return TRUE;
-case MJPEG_ENCODER_FRAME_UNSUPPORTED:
+case VIDEO_ENCODER_FRAME_UNSUPPORTED:
 return FALSE;
-case MJPEG_ENCODER_FRAME_ENCODE_START:
+case VIDEO_ENCODER_FRAME_ENCODE_DONE:
 break;
 default:
-spice_error(bad return value (%d) from mjpeg_encoder_start_frame, 
ret);
-return FALSE;
-}
-
-if (!encode_frame(dcc, drawable-red_drawable-u.copy.src_area,
-  image-u.bitmap, stream)) {
+spice_error(bad return value (%d) from VideoEncoder::encode_frame, 
ret);
 return FALSE;
 }
-n = mjpeg_encoder_end_frame(agent-mjpeg_encoder);
 dcc-send_data.stream_outbuf_size = outbuf_size;
 
 if (!drawable-sized_stream) {
@@ -10255,7 +10187,7 @@ static int 
display_channel_handle_stream_report(DisplayChannelClient *dcc,
 return FALSE;
 }
 stream_agent = dcc-stream_agents[stream_report-stream_id];
-if (!stream_agent-mjpeg_encoder) {
+if (!stream_agent-video_encoder) {
 spice_info(stream_report: no encoder for stream id %u.
 Probably the stream has been destroyed, 
stream_report-stream_id);
 return TRUE;
@@ -10266,7 +10198,7 @@ static int 
display_channel_handle_stream_report(DisplayChannelClient *dcc,
   stream_agent-report_id, stream_report-unique_id);
 return TRUE;
 }
-mjpeg_encoder_client_stream_report(stream_agent-mjpeg_encoder,
+
stream_agent-video_encoder-client_stream_report(stream_agent-video_encoder,
stream_report-num_frames,
stream_report-num_drops,
stream_report-start_frame_mm_time,
diff --git a/server/video_encoder.h b/server/video_encoder.h
new file mode 100644
index 000..8a9f9c6
--- /dev/null
+++ b/server/video_encoder.h
@@ -0,0 +1,162 @@
+/* -*- Mode: C; c-basic-offset: 4; indent-tabs-mode: nil -*- */
+/*
+   Copyright (C) 2009 Red Hat, Inc.
+   Copyright (C) 2015 Jeremy White
+   Copyright (C) 2015 Francois Gouget
+
+   This library is free software; you can redistribute it and/or
+   modify it under the terms of the GNU Lesser General Public
+   License as published by the Free Software Foundation; either
+   version 2.1 of the License, or (at your option) any later version.
+
+   This library is distributed in the hope that it will be useful,
+   but WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+   Lesser General Public License for more details.
+
+   You should have received a copy of the GNU Lesser General Public
+   License along with this library; if not, see A 
HREF=http://www.gnu.org/licenses/;http://www.gnu.org/licenses//A.
+*/
+
+#ifndef _H_video_encoder
+#define _H_video_encoder
+
+#include red_common.h
+
+enum {
+VIDEO_ENCODER_FRAME_UNSUPPORTED = -1,
+VIDEO_ENCODER_FRAME_DROP,
+VIDEO_ENCODER_FRAME_ENCODE_DONE,
+};
+
+typedef struct VideoEncoderStats {
+uint64_t starting_bit_rate;
+uint64_t cur_bit_rate;
+double avg_quality;
+} VideoEncoderStats;
+
+typedef struct VideoEncoder VideoEncoder;
+#ifndef VIDEO_ENCODER_T
+# define VIDEO_ENCODER_T VideoEncoder
+#endif
+
+struct VideoEncoder {
+/* Releases the video encoder's resources */
+void (*destroy)(VIDEO_ENCODER_T *encoder);
+
+/* Compresses the specified src image area into the outbuf buffer.
+ *
+ * @encoder:   The video encoder.
+ * @bitmap:The Spice screen.
+ * @width: The width of the Spice screen.
+ * @height:The heigth of the Spice screen.
+ * @src:   A rectangle specifying the area occupied by the video.
+ * @top_down:  If true the first video line is specified by src.top.
+ * @outbuf:The buffer for the compressed frame. This must either be
+ * NULL or point to a buffer allocated by malloc since it may 
be
+ * reallocated, if its size is too small.
+ * @outbuf_size

[Spice-devel] [PATCH spice] server: Round the framerate estimate to the nearest integer.

2015-06-08 Thread Francois Gouget
This is more accurate for typical values like 23.976 fps.
---
 server/red_worker.c | 6 +++---
 1 file changed, 3 insertions(+), 3 deletions(-)

diff --git a/server/red_worker.c b/server/red_worker.c
index cc0a116..0207977 100644
--- a/server/red_worker.c
+++ b/server/red_worker.c
@@ -3159,15 +3159,15 @@ static void red_stream_input_fps_timer_cb(void *opaque)
 {
 Stream *stream = opaque;
 uint64_t now = red_now();
-double duration_sec;
 
 spice_assert(opaque);
 if (now == stream-input_fps_timer_start) {
 spice_warning(timer start and expiry time are equal);
 return;
 }
-duration_sec = (now - stream-input_fps_timer_start)/(1000.0*1000*1000);
-stream-input_fps = stream-num_input_frames / duration_sec;
+/* Round to the nearest integer, for instance 24 for 23.976 */
+uint64_t duration = now - stream-input_fps_timer_start;
+stream-input_fps = ((uint64_t)stream-num_input_frames * 1000 * 1000 * 
1000 + duration / 2) / duration;
 spice_debug(input-fps=%u, stream-input_fps);
 stream-num_input_frames = 0;
 stream-input_fps_timer_start = now;
-- 
2.1.4
___
Spice-devel mailing list
Spice-devel@lists.freedesktop.org
http://lists.freedesktop.org/mailman/listinfo/spice-devel


Re: [Spice-devel] [PATCH 0/11] Add GStreamer and VP8 support

2015-06-09 Thread Francois Gouget
On Thu, 4 Jun 2015, Fabio Fantoni wrote:
[...]
 No bandwidth limit, on client I saw use between 1 and 3 mb, both server
 and client have 1 gbps cabled network (lan).
 Server used for testing is a dell PE T310 with cpu xeon X3450 is asus
 K53S with core i5-2430M.
 Server cpu usage of qemu process is over 300% on streming video.
 spice streaming video setting is 'all' and codec 'gstreamer:vp8', no
 error/warning in qemu logs.
 I used github.com/fgouget/spice-gtk/commits/gst including avoid
 gstreamer deadlock and github.com/fgouget/spice/commits/gst in latest test.
 Client cpu and network usage seems low but streaming video is bad (with
 vp8), here a small video example done with smartphone:
 http://fantu.it/vari/spice-gtk-vp8.mp4

The video looks like there are two issues:

* The video corruption. It looks like an I frame was lost and the
  following P frames were thus decoded incorrectly. This is a bit 
  strange because in my experience VP8 throws the P frames in such a 
  case (so they are not displayed, unlike in h264's case).

* The short pause every few seconds. This may be related to the previous 
  issue: I frames are bigger than P frames. Maybe they take too long 
  coming across, thus forcing the client to pause waiting for them, and 
  maybe that's also why they sometimes get lost.

But given your network specifications that should not be the case. I 
have done tests with StreamingVideo=all here but it worked as well as 
when set to filter so that's probably not the source of the difference.

Overall I suspect more a problem on the server-side. Here's what you can 
do:

* First on the server check for messages that indicate some frames 
  were dropped like the ones below (SPICE_DEBUG_LEVEL=9):

  (../xf86-video-qxl/scripts/Xspice:31980): SpiceWorker-Debug **: 
red_worker.c:3378:pre_stream_item_swap: ignoring drop, same pcg as 
previous frame 296
  (../xf86-video-qxl/scripts/Xspice:31980): SpiceWorker-Debug **: 
red_worker.c:10643:display_channel_release_item: not pushed (101)

  As far as I understand it's the second message that indicates a frame 
  has been dropped, but it systematically follows the first one so they 
  are related. These happen even when there's no bandwidth issue and 
  only happen in the GStreamer 1.0 case. And I have no idea what's 
  causing this so far :-(

* You can also look for 'server frame drop' in the server log. 
  Unlike the messages above, those would indicate a network problem.

* In gstreamer_encoder.c you may try adding a line like the following 
  near the start of adjust_bit_rate() to see if constraining the 
  bandwidth helps:
encoder-bit_rate = 1024 * 1024 * 3;

  In the server log you can also look for 'base-bit-rate' and 'setting 
  the bit rate' to see what Spice and gstreamer_encoder think of the 
  bitrate respectively.

* Do you have the same issue if you use gstreamer:mjpeg on the 
  server? If gstreamer:mjpeg works fine then we'll know 
  it's not a general GStreamer issue but more a codec-specific one.

* The next thing to try would be gstreamer:h264. h264 is quite similar 
  to vp8 in caracteristics: it has I and P frames too and also uses 
  quite a bit of CPU, though it seems to handle threading a bit 
  better.

* Then if you can try running the server with GStreamer 0.10 this would 
  let us determine if it's a GStreamer version problem.

* The CPU usage on the server, 300%, does seem a bit high though for a 
  4C/8T CPU it should be manageable. Unfortunately gstreamer_encoder 
  already tunes vp8enc for speed. Maybe setting threads=4 or 5, or 
  cpu-used=16 can speed it up some more. For network usage maybe 
  max-intra-bitrate can help.


-- 
Francois Gouget fgou...@codeweavers.com
___
Spice-devel mailing list
Spice-devel@lists.freedesktop.org
http://lists.freedesktop.org/mailman/listinfo/spice-devel


[Spice-devel] RFC spice: Should the input-fps be refreshed regularly?

2015-06-09 Thread Francois Gouget

Spice provides an estimate of the input video fps to the video streaming 
backends. This is done by red_stream_input_fps_timer_cb() in 
red_worker.c which is called 5 seconds after the streaming starts.

That callback contains code so it can be called again:

stream-num_input_frames = 0;
stream-input_fps_timer_start = now;

However the corresponding timer is not rearmed so it is in fact called 
only once. Is that the correct behavior or do we want the input_fps 
field to be refreshed regularly?

For video the framerate tends to be pretty constant so calculating it 
once could be sufficient. But maybe there are other cases where we would 
want more up to date information. Games maybe?


-- 
Francois Gouget fgou...@codeweavers.com
___
Spice-devel mailing list
Spice-devel@lists.freedesktop.org
http://lists.freedesktop.org/mailman/listinfo/spice-devel


Re: [Spice-devel] Status of spice-html5 and video streaming

2015-06-06 Thread Francois Gouget
On Fri, 5 Jun 2015, Jeremy White wrote:
[...]
 I haven't had a chance to work this in with the vp8 code, which I had
 hoped would provide a dramatic improvement.  Unfortunately, the sized
 stream message really creates havoc with vp8 streams, and you really
 can't play a video without the sized stream messages.  See:
   http://lists.freedesktop.org/archives/spice-devel/2015-May/019948.html

One way to test things without running into the sized stream issues is 
to use mplayer. It has no GUI so no progress bar or other menus to 
confuse Spice:

   DISPLAY=:3.0 mplayer big_buck_bunny_480p_h264.mov


-- 
Francois Gouget fgou...@codeweavers.com
___
Spice-devel mailing list
Spice-devel@lists.freedesktop.org
http://lists.freedesktop.org/mailman/listinfo/spice-devel


[Spice-devel] [PATCH qxl] spiceqxl: Recognize the same set of boolean values as in xorg.conf.

2015-06-08 Thread Francois Gouget
Report an error if an invalid boolean value is used, just like for other 
options.
---

This seems simple enough and may avoid confusion.

 src/qxl_option_helpers.c | 27 ---
 1 file changed, 20 insertions(+), 7 deletions(-)

diff --git a/src/qxl_option_helpers.c b/src/qxl_option_helpers.c
index 8801b53..c9ad726 100644
--- a/src/qxl_option_helpers.c
+++ b/src/qxl_option_helpers.c
@@ -3,6 +3,7 @@
 #endif
 
 #include stdlib.h
+#include strings.h
 
 #include xf86.h
 #include xf86Opt.h
@@ -30,12 +31,24 @@ const char *get_str_option(OptionInfoPtr options, int 
option_index,
 int get_bool_option(OptionInfoPtr options, int option_index,
  const char *env_name)
 {
-if (getenv(env_name)) {
-/* we don't support the whole range of boolean true and
- * false values documented in man xorg.conf, just the c
- * convention - 0 is false, anything else is true, so
- * just like a number. */
-return !!atoi(getenv(env_name));
+const char* value = getenv(env_name);
+
+if (!value) {
+return options[option_index].value.bool;
+}
+if (strcmp(value, 1) == 0 ||
+strcasecmp(value, on) == 0 ||
+strcasecmp(value, true) == 0 ||
+strcasecmp(value, yes) == 0) {
+return TRUE;
 }
-return options[option_index].value.bool;
+if (strcmp(value, 0) == 0 ||
+strcasecmp(value, off) == 0 ||
+strcasecmp(value, false) == 0 ||
+strcasecmp(value, no) == 0) {
+return FALSE;
+}
+
+fprintf(stderr, spice: invalid %s: %s\n, env_name, value);
+exit(1);
 }
-- 
2.1.4

___
Spice-devel mailing list
Spice-devel@lists.freedesktop.org
http://lists.freedesktop.org/mailman/listinfo/spice-devel


[Spice-devel] [PATCH qxl] Xspice: Don't set defaults for the options.

2015-06-08 Thread Francois Gouget
Otherwise they override Spice server's real builtin defaults, the Xorg 
configuration file settings, and even the XSPICE_XXX environment variables.
---

Without this patch, calling Xspice _without_ the '--streaming-video' 
option forces this setting to 'filter', overriding the 
XSPICE_STREAMING_VIDEO environment variable and the SpiceStreamingVideo 
spiceqxl.xorg.conf setting.

 scripts/Xspice | 16 
 1 file changed, 8 insertions(+), 8 deletions(-)

diff --git a/scripts/Xspice b/scripts/Xspice
index 281535d..f565eb1 100755
--- a/scripts/Xspice
+++ b/scripts/Xspice
@@ -45,7 +45,7 @@ else:
 cgdb = None
 
 def add_boolean(flag, *args, **kw):
-parser.add_argument(flag, action='store_const', const='1', default='0',
+parser.add_argument(flag, action='store_const', const='1',
 *args, **kw)
 
 wan_compression_options = ['auto', 'never', 'always']
@@ -65,7 +65,7 @@ parser.add_argument('--deferred-fps', type=int, help='If 
given, render to a buff
 parser.add_argument('--tls-port', type=int, help='spice tls port', default=0)
 add_boolean('--disable-ticketing', help=do not require a client password)
 add_boolean('--sasl', help=enable sasl)
-parser.add_argument('--x509-dir', help=x509 directory for tls, default='.')
+parser.add_argument('--x509-dir', help=x509 directory for tls)
 parser.add_argument('--cacert-file', help=ca certificate file for tls)
 parser.add_argument('--x509-cert-file', help=server certificate file for tls)
 parser.add_argument('--x509-key-file', help=server key file for tls)
@@ -76,16 +76,16 @@ parser.add_argument('--password', help=set password 
required to connect to serv
 parser.add_argument('--image-compression',
 choices = ['off', 'auto_glz', 'auto_lz', 'quic',
'glz', 'lz'],
-default='auto_glz', help='auto_glz by default')
+help='auto_glz by default')
 parser.add_argument('--jpeg-wan-compression',
 choices=wan_compression_options,
-default='auto', help='auto by default')
+help='auto by default')
 parser.add_argument('--zlib-glz-wan-compression',
 choices=wan_compression_options,
-default='auto', help='auto by default')
+help='auto by default')
 # TODO - sound support
 parser.add_argument('--streaming-video', choices=['off', 'all', 'filter'],
-default='filter', help='filter by default')
+help='filter by default')
 add_boolean('--ipv4-only')
 add_boolean('--ipv6-only')
 parser.add_argument('--vdagent', action='store_true', dest='vdagent_enabled', 
default=False, help='launch vdagent  vdagentd. They provide clipboard  
resolution automation')
@@ -96,7 +96,7 @@ parser.add_argument('--vdagent-exec', help='path to 
spice-vdagent (used with --v
 parser.add_argument('--vdagent-no-launch', default=True, action='store_false', 
dest='vdagent_launch', help='do not launch vdagent  vdagentd, used for 
debugging or if some external script wants to take care of that')
 parser.add_argument('--vdagent-uid', default=str(os.getuid()), help='set 
vdagent user id. changing it makes sense only in conjunction with 
--vdagent-no-launch')
 parser.add_argument('--vdagent-gid', default=str(os.getgid()), help='set 
vdagent group id. changing it makes sense only in conjunction with 
--vdagent-no-launch')
-parser.add_argument('--audio-fifo-dir', default='', help=set fifo directory 
for playback audio. designed to work with PulseAudio's module-pipe-sink)
+parser.add_argument('--audio-fifo-dir', help=set fifo directory for playback 
audio. designed to work with PulseAudio's module-pipe-sink)
 
 #TODO
 #Option SpiceAddr 
@@ -105,7 +105,7 @@ parser.add_argument('--audio-fifo-dir', default='', 
help=set fifo directory for
 #Option EnableFallbackCache True
 #Option EnableSurfaces True
 #Option NumHeads 4
-#parser.add_argument('--playback-compression', choices=['0', '1'], 
default='1', help='enabled by default')
+#parser.add_argument('--playback-compression', choices=['0', '1'], 
help='enabled by default')
 #Option SpiceDisableCopyPaste False
 
 if cgdb:
-- 
2.1.4
___
Spice-devel mailing list
Spice-devel@lists.freedesktop.org
http://lists.freedesktop.org/mailman/listinfo/spice-devel


Re: [Spice-devel] [PATCH spice] server: Remove an unused structure.

2015-06-08 Thread Francois Gouget
On Wed, 27 May 2015, Francois Gouget wrote:

 ---
 
 This struct was introduced in the first commit, c1b79eb0, about 6 years 
 ago, but has never been used. So I think it's safe to remove.

Is something holding up this patch?
Does it need modifications for inclusion?

-- 
Francois Gouget fgou...@codeweavers.com
___
Spice-devel mailing list
Spice-devel@lists.freedesktop.org
http://lists.freedesktop.org/mailman/listinfo/spice-devel


Re: [Spice-devel] [PATCH spice 1/2] server: Refresh the input fps every 5 second, without a timer.

2015-06-22 Thread Francois Gouget
On Thu, 11 Jun 2015, Francois Gouget wrote:

 Signed-off-by: Francois Gouget fgou...@codeweavers.com
 ---
 
 This implements Marc-André Lureau's suggestion:
 http://lists.freedesktop.org/archives/spice-devel/2015-June/020202.html
 
 And supersedes the input-fps rounding patch.
 http://lists.freedesktop.org/archives/spice-devel/2015-June/020176.html

Does this patch series need modifications for inclusion?

-- 
Francois Gouget fgou...@codeweavers.com___
Spice-devel mailing list
Spice-devel@lists.freedesktop.org
http://lists.freedesktop.org/mailman/listinfo/spice-devel


Re: [Spice-devel] [PATCH spice 1/12] server: Convert a couple of rate control checks into asserts in the mjpeg video encoder. (take 3)

2015-06-22 Thread Francois Gouget
On Wed, 10 Jun 2015, Francois Gouget wrote:

 The checks would lead the reader to think these functions can be called when 
 bit rate control is off when in fact they are only called when it is active.
 
 Signed-off-by: Francois Gouget fgou...@codeweavers.com
 ---
 
 This patch stands on its own and I think it makes sense even if the 
 remainder of the series is not applied. It seemed ok in round 1 so 
 again no change this time around. Let me know if it needs further 
 refinements for inclusion.

This patch was acked a while ago but has not been committed yet.
Does it need changes? Should I drop it from the series?
(Same thing for the next one, 2/12)

http://lists.freedesktop.org/archives/spice-devel/2015-May/019843.html



  server/mjpeg_encoder.c | 9 +++--
  1 file changed, 3 insertions(+), 6 deletions(-)
 
 diff --git a/server/mjpeg_encoder.c b/server/mjpeg_encoder.c
 index 12447da..95d841f 100644
 --- a/server/mjpeg_encoder.c
 +++ b/server/mjpeg_encoder.c
 @@ -607,9 +607,7 @@ static void 
 mjpeg_encoder_adjust_params_to_bit_rate(MJpegEncoder *encoder)
  uint32_t latency = 0;
  uint32_t src_fps;
  
 -if (!encoder-rate_control_is_active) {
 -return;
 -}
 +spice_assert(encoder-rate_control_is_active);
  
  rate_control = encoder-rate_control;
  quality_eval = rate_control-quality_eval_data;
 @@ -694,9 +692,8 @@ static void mjpeg_encoder_adjust_fps(MJpegEncoder 
 *encoder, uint64_t now)
  MJpegEncoderRateControl *rate_control = encoder-rate_control;
  uint64_t adjusted_fps_time_passed;
  
 -if (!encoder-rate_control_is_active) {
 -return;
 -}
 +spice_assert(encoder-rate_control_is_active);
 +
  adjusted_fps_time_passed = (now - rate_control-adjusted_fps_start_time) 
 / 1000 / 1000;
  
  if (!rate_control-during_quality_eval 
 -- 
 2.1.4



-- 
Francois Gouget fgou...@codeweavers.com
___
Spice-devel mailing list
Spice-devel@lists.freedesktop.org
http://lists.freedesktop.org/mailman/listinfo/spice-devel


[Spice-devel] [PATCH common 5/12] spice.proto: Add support for the VP8 and H264 video codecs. (take 3)

2015-06-10 Thread Francois Gouget

Signed-off-by: Francois Gouget fgou...@codeweavers.com
---

Changes since take 2:
- This patch also adds h264.

 spice.proto | 2 ++
 1 file changed, 2 insertions(+)

diff --git a/spice.proto b/spice.proto
index 01493c9..95123ae 100644
--- a/spice.proto
+++ b/spice.proto
@@ -329,6 +329,8 @@ flags8 path_flags { /* TODO: C enum names changes */
 
 enum8 video_codec_type {
 MJPEG = 1,
+VP8,
+H264,
 };
 
 flags8 stream_flags {
-- 
2.1.4

___
Spice-devel mailing list
Spice-devel@lists.freedesktop.org
http://lists.freedesktop.org/mailman/listinfo/spice-devel


[Spice-devel] [PATCH spice 4/12] server: Add a GStreamer 0.10 MJPEG video encoder and use it by default. (take 3)

2015-06-10 Thread Francois Gouget
The GStreamer video encoder supports both regular and sized streamsi.
It is otherwise quite basic and lacks any rate control: the bitrate is set at 
startup and will not react to changes in the network conditions. Still it 
should work fine on LANs.

Signed-off-by: Francois Gouget fgou...@codeweavers.com
---

This does not use encodebin because we really need to know much about 
the encoder:
- We need to disable B frames for encoders that support inter-frame 
  compression (see the VP8 and h264 patches).
- We need to be able to set the bitrate which the encoder may want to 
  get in either bits/second or kilobits/second.
- We also have to configure the encoder for speed since we need it to 
  work in real time.

As far as I can tell there is no standardized way to specify this so we 
need intimate knowledge of the encoder parameters.


Changes since take 2:
- I resolved the buffer timestamping issues. Appsrc is no longer a live 
  source (it had no reason to be) and it performs the timestamping. The 
  only remaining annoyance is that ffenc_mjpeg requires removing the 
  pipeline's default clock otherwise it gets stuck with the following 
  message:

  ERROR  ffmpeg :0:: Error, Invalid timestamp=0, last=0

  I consider this to be an ffenc_mjpeg bug since none of the other 
  encoders (VP8, H264 and even avenc_mpjpeg in GStreamer 1.0) has this 
  issue. So I'm keeping the clock removal as a workaround for 
  ffenc_mjpeg.

- I went back to ffmpegcolorspace because it's the standard way to do 
  color conversion in GStreamer 0.10 (present in gst-plugins-base), 
  while autovideoconvert is only present in gst-plugins-bad which I 
  believe we don't depend on.

- I simplified the source frame copy code (push_raw_frame()). It's also 
  ready for adding zero-copy once GStreamer 1.0 support is added.

- I improved the autoconf GStreamer 0.10 detection: it's now possible 
  to require GStreamer support, or just let it be included if present. 
  This also paves the way for GStreamer 1.0.

- Changed set_appsrc_caps() and construct_pipeline() to return a 
  gboolean since they only return TRUE/FALSE.

- Fixed some formatting issues, mostly braces placement.

Changes since take 1:
- The width/height comments are now correct in the previous patch of
  the series.

- Fixed the pipeline reconfiguration (for video size changes) so it 
  still works if we have to fall back to rebuilding the pipeline from 
  scratch.

- Added a comment suggesting to avoid copying the compressed buffer as 
  a future improvement. I think this will require changing the way the 
  output buffer is allocated though. So I'm leaving that for after the 
  basic support committed.


 configure.ac   |  27 ++-
 server/Makefile.am |   8 +
 server/gstreamer_encoder.c | 434 +
 server/red_worker.c|  11 +-
 server/video_encoder.h |   6 +
 5 files changed, 483 insertions(+), 3 deletions(-)
 create mode 100644 server/gstreamer_encoder.c

diff --git a/configure.ac b/configure.ac
index 7a9fc4b..34e1a4a 100644
--- a/configure.ac
+++ b/configure.ac
@@ -91,6 +91,30 @@ if test x$enable_smartcard = xyes; then
AC_DEFINE([USE_SMARTCARD], [1], [Define if supporting smartcard proxying])
 fi
 
+AC_ARG_ENABLE(gstreamer,
+  AS_HELP_STRING([--enable-gstreamer=@:@auto/yes/no@:@],
+ [Enable GStreamer 0.10 support]),
+  [],
+  [enable_gstreamer=auto])
+
+if test x$enable_gstreamer != xno; then
+PKG_CHECK_MODULES(GSTREAMER_0_10, [gstreamer-0.10, gstreamer-app-0.10],
+  [enable_gstreamer=yes
+   have_gstreamer_0_10=yes],
+  [have_gstreamer_0_10=no])
+if test x$have_gstreamer_0_10 = xyes; then
+AC_SUBST(GSTREAMER_0_10_CFLAGS)
+AC_SUBST(GSTREAMER_0_10_LIBS)
+AS_VAR_APPEND([SPICE_REQUIRES], [ gstreamer-0.10 gstreamer-app-0.10])
+AC_DEFINE([HAVE_GSTREAMER_0_10], [1], [Define if supporting GStreamer 
0.10])
+elif test x$enable_gstreamer = xyes; then
+AC_MSG_ERROR([GStreamer 0.10 support requested but not found. You may 
set GSTREAMER_0_10_CFLAGS and GSTREAMER_0_10_LIBS to avoid the need to call 
pkg-config.])
+fi
+else
+have_gstreamer_0_10=no
+fi
+AM_CONDITIONAL(SUPPORT_GSTREAMER_0_10, test x$have_gstreamer_0_10 = xyes)
+
 AC_ARG_ENABLE(automated_tests,
 [  --enable-automated-tests Enable automated tests using spicy-screenshot 
(part of spice--gtk)],,
 [enable_automated_tests=no])
@@ -127,7 +151,6 @@ if test x$enable_smartcard = xyes; then
 AS_VAR_APPEND([SPICE_REQUIRES], [ libcacard = 0.1.2])
 fi
 
-
 PKG_CHECK_MODULES([GLIB2], [glib-2.0 = 2.22])
 AS_VAR_APPEND([SPICE_REQUIRES], [ glib-2.0 = 2.22])
 
@@ -359,6 +382,8 @@ echo 
 
 Smartcard:${enable_smartcard}
 
+GStreamer 0.10:   ${have_gstreamer_0_10}
+
 SASL support: ${enable_sasl}
 
 Automated

[Spice-devel] [PATCH spice 7/12] server: Add VP8 support, a video codec preference list and compatibility checks with the Spice client. (take 3)

2015-06-10 Thread Francois Gouget
The video encoder preferences can be expressed by building a semi-colon 
separated list of encoder:codec pairs. For instance 'gstreamer:vp8;spice:mjpeg' 
to pick first the GStreamer VP8 video encoder first and used the original MJPEG 
video encoder one as a fallback.
The server has a default preference list which can also be selected by 
specifying 'auto' as the preferences list.
The client compatibility check relies on the following new 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, for now MJPEG 
and VP8.

Signed-off-by: Francois Gouget fgou...@codeweavers.com
---

Note that this patch should be preceded by one that grabs the right 
spice-common commit so we get the new codec and capability constants.

Changes since take 2:
- We now allow the VP8 encoder to produce P frames since this does not 
  increase the latency (i.e. it still lets us get the compressed frames 
  right away), while improving the compression ratio.

- It turns out the above also helps with CPU usage and lets us 
  further configure the encoder for speed.

- Only construct_pipeline() really needs to know the encoder name so 
  we no longer keep it in a GstEncoder field.

- Fixed some formatting issues, mostly braces placement.

Changes since take 1:
- Only set the parameters supported by the current encoder.

- reconfigure_pipeline() handling has been fixed in the previous patch.

- The video codecs list now has a more sensible default and it's 
  possible to explicitly request this default by specifying 'auto' in 
  the configuration files.


 server/gstreamer_encoder.c |  61 +---
 server/mjpeg_encoder.c |   7 +-
 server/red_dispatcher.c| 172 -
 server/red_dispatcher.h|   8 +++
 server/red_worker.c|  65 ++---
 server/red_worker.h|  18 +
 server/reds.c  |  13 
 server/spice-server.h  |   1 +
 server/spice-server.syms   |   1 +
 server/video_encoder.h |  18 +++--
 10 files changed, 321 insertions(+), 43 deletions(-)

diff --git a/server/gstreamer_encoder.c b/server/gstreamer_encoder.c
index 3600b1b..e7c9a56 100644
--- a/server/gstreamer_encoder.c
+++ b/server/gstreamer_encoder.c
@@ -178,10 +178,27 @@ static gboolean set_appsrc_caps(GstEncoder *encoder)
 
 static gboolean construct_pipeline(GstEncoder *encoder, const SpiceBitmap 
*bitmap)
 {
+gboolean no_clock = FALSE;
+const gchar* gstenc_name;
+switch (encoder-base.codec_type)
+{
+case SPICE_VIDEO_CODEC_TYPE_MJPEG:
+gstenc_name = ffenc_mjpeg;
+no_clock = TRUE;
+break;
+case SPICE_VIDEO_CODEC_TYPE_VP8:
+gstenc_name = vp8enc;
+break;
+default:
+spice_warning(unsupported codec type %d, encoder-base.codec_type);
+return FALSE;
+}
+
 GError *err = NULL;
-const gchar* desc = appsrc name=src format=2 do-timestamp=true ! 
ffmpegcolorspace ! ffenc_mjpeg name=encoder ! appsink name=sink;
+gchar *desc = g_strdup_printf(appsrc name=src format=2 do-timestamp=true 
! ffmpegcolorspace ! %s name=encoder ! appsink name=sink, gstenc_name);
 spice_debug(GStreamer pipeline: %s, desc);
 encoder-pipeline = gst_parse_launch_full(desc, NULL, 
GST_PARSE_FLAG_FATAL_ERRORS, err);
+g_free(desc);
 if (!encoder-pipeline) {
 spice_warning(GStreamer error: %s, err-message);
 g_clear_error(err);
@@ -191,19 +208,31 @@ static gboolean construct_pipeline(GstEncoder *encoder, 
const SpiceBitmap *bitma
 encoder-gstenc = gst_bin_get_by_name(GST_BIN(encoder-pipeline), 
encoder);
 encoder-appsink = 
GST_APP_SINK(gst_bin_get_by_name(GST_BIN(encoder-pipeline), sink));
 
+/* Set the encoder initial bit rate, and ask for a low latency */
+adjust_bit_rate(encoder);
+g_object_set(G_OBJECT(encoder-gstenc), bitrate, encoder-bit_rate, 
NULL);
+if (encoder-base.codec_type == SPICE_VIDEO_CODEC_TYPE_VP8) {
+/* See http://www.webmproject.org/docs/encoder-parameters/ */
+g_object_set(G_OBJECT(encoder-gstenc),
+ mode, 1, /* CBR */
+ max-latency, 0,
+ speed, 7,
+ resize-allowed, TRUE,
+ threads, g_get_num_processors() - 1,
+ NULL);
+}
+
 /* Set the source caps */
 encoder-src_caps = NULL;
 if (!set_appsrc_caps(encoder)) {
 return FALSE;
 }
 
-/* Set the encoder initial bit rate */
-adjust_bit_rate(encoder);
-g_object_set(G_OBJECT(encoder-gstenc), bitrate, encoder-bit_rate, 
NULL);
-
 /* Start playing */
-spice_debug(removing the pipeline clock);
-gst_pipeline_use_clock(GST_PIPELINE(encoder-pipeline), NULL

[Spice-devel] [PATCH spice 12/12] server: Add h264 support to the GStreamer video encoder.

2015-06-10 Thread Francois Gouget

Signed-off-by: Francois Gouget fgou...@codeweavers.com
---

Having support for h264 is interesting in its own right but this shows 
adding extra codecs is quite easy.

 server/gstreamer_encoder.c | 17 -
 server/red_dispatcher.c|  2 ++
 2 files changed, 18 insertions(+), 1 deletion(-)

diff --git a/server/gstreamer_encoder.c b/server/gstreamer_encoder.c
index 6a47668..451518f 100644
--- a/server/gstreamer_encoder.c
+++ b/server/gstreamer_encoder.c
@@ -204,6 +204,9 @@ static gboolean construct_pipeline(GstEncoder *encoder, 
const SpiceBitmap *bitma
 case SPICE_VIDEO_CODEC_TYPE_VP8:
 gstenc_name = vp8enc;
 break;
+case SPICE_VIDEO_CODEC_TYPE_H264:
+gstenc_name = x264enc;
+break;
 default:
 spice_warning(unsupported codec type %d, encoder-base.codec_type);
 return FALSE;
@@ -254,6 +257,17 @@ static gboolean construct_pipeline(GstEncoder *encoder, 
const SpiceBitmap *bitma
  threads, g_get_num_processors() - 1,
  NULL);
 break;
+case SPICE_VIDEO_CODEC_TYPE_H264:
+g_object_set(G_OBJECT(encoder-gstenc),
+ bitrate, encoder-bit_rate / 1024,
+ byte-stream, TRUE,
+ aud, FALSE,
+ tune, 4, /* Zero latency */
+ intra-refresh, TRUE,
+ sliced-threads, TRUE,
+ speed-preset, 1, /* ultrafast */
+ NULL);
+break;
 default:
 spice_warning(unknown encoder type %d, encoder-base.codec_type);
 reset_pipeline(encoder);
@@ -587,7 +601,8 @@ GstEncoder *create_gstreamer_encoder(SpiceVideoCodecType 
codec_type, uint64_t st
 
 spice_assert(!cbs || (cbs  cbs-get_roundtrip_ms  
cbs-get_source_fps));
 if (codec_type != SPICE_VIDEO_CODEC_TYPE_MJPEG 
-codec_type != SPICE_VIDEO_CODEC_TYPE_VP8) {
+codec_type != SPICE_VIDEO_CODEC_TYPE_VP8 
+codec_type != SPICE_VIDEO_CODEC_TYPE_H264) {
 spice_warning(unsupported codec type %d, codec_type);
 return NULL;
 }
diff --git a/server/red_dispatcher.c b/server/red_dispatcher.c
index 08623e2..a034949 100644
--- a/server/red_dispatcher.c
+++ b/server/red_dispatcher.c
@@ -267,12 +267,14 @@ static create_video_encoder_proc video_encoder_procs[] = {
 static const EnumNames video_codec_names[] = {
 {SPICE_VIDEO_CODEC_TYPE_MJPEG, mjpeg},
 {SPICE_VIDEO_CODEC_TYPE_VP8, vp8},
+{SPICE_VIDEO_CODEC_TYPE_H264, h264},
 {0, NULL},
 };
 
 static const EnumNames video_cap_names[] = {
 {SPICE_DISPLAY_CAP_CODEC_MJPEG, mjpeg},
 {SPICE_DISPLAY_CAP_CODEC_VP8, vp8},
+{SPICE_DISPLAY_CAP_CODEC_H264, h264},
 {0, NULL},
 };
 
-- 
2.1.4
___
Spice-devel mailing list
Spice-devel@lists.freedesktop.org
http://lists.freedesktop.org/mailman/listinfo/spice-devel


[Spice-devel] [PATCH spice 11/12] server: Avoid copying the input frame in the GStreamer encoder.

2015-06-10 Thread Francois Gouget
To do so we reference the source bitmap chunks in the GStreamer buffer and rely 
on the buffer's lifetime being short enough.
Note that we can only avoid copies for the first 1 Mpixels or so. That's 
because Spice splits larger frames into more chunks and we can fit memory 
fragments inside a GStreamer buffer. So for those we will avoid copies for the 
first 3840 KB and copy the rest.

Signed-off-by: Francois Gouget fgou...@codeweavers.com
---

This makes it possible to avoid copying the source frame when using
GStreamer 1.0. Paradoxically we are still forced to do some copying for
the larger frames.

Here is how it works: Spice's frame buffer is composed of multiple 
memory chunks. So we use GStreamer's GstMemory objects to wrap each 
chunk and put them all to form the GstBuffer we pass to the pipeline. 
However there's a limit to the number of memory objects that we can put 
in a GstBuffer. Usually that limit is 16. Furthermore Spice splits the 
frame into 256KB chunks. so this approach only works up to 4MB or 
between 1 and 1.3Mpixels. For larger frames we use the zero-copy 
approach for the first 15 frame chunks, and copy all the rest into the 
16th memory chunk.

So on my machine, for a 720x304 video the frame copy time goes from 
around 265us (line-by-line) to 5us. For a 1440x900 frame it goes from 
about 1610us with the old line-by-line copy code, down to 1490us for the 
new chunk-by-chunk one, and down to about 440us when minimizing copies. 
The latter matches well with the ~0.3Mpixels we have to copy after the 
first 1Mpixels.

To avoid these copies it will be necessary to either increase the size 
of the Spice chunks or to increase the number of memory objects that 
GstBuffers can hold.


 server/gstreamer_encoder.c | 108 +
 1 file changed, 100 insertions(+), 8 deletions(-)

diff --git a/server/gstreamer_encoder.c b/server/gstreamer_encoder.c
index 97e6e13..9731ebb 100644
--- a/server/gstreamer_encoder.c
+++ b/server/gstreamer_encoder.c
@@ -33,6 +33,10 @@ typedef struct GstEncoder GstEncoder;
 
 #define DEFAULT_FPS 30
 
+#ifndef HAVE_GSTREAMER_0_10
+# define DO_ZERO_COPY
+#endif
+
 
 typedef struct {
 SpiceBitmapFmt  spice_format;
@@ -64,6 +68,9 @@ struct GstEncoder {
 int height;
 SpiceFormatForGStreamer *format;
 SpiceBitmapFmt spice_format;
+#ifdef DO_ZERO_COPY
+gboolean needs_bitmap;
+#endif
 
 /* Rate control information */
 uint64_t bit_rate;
@@ -289,21 +296,28 @@ static void reconfigure_pipeline(GstEncoder *encoder)
 }
 }
 
+#ifdef DO_ZERO_COPY
+static void unref_bitmap(gpointer mem)
+{
+GstEncoder *encoder = (GstEncoder*)mem;
+encoder-needs_bitmap = FALSE;
+}
+#endif
+
 static int push_raw_frame(GstEncoder *encoder, const SpiceBitmap *bitmap,
   const SpiceRect *src, int top_down)
 {
 const uint32_t stream_height = src-bottom - src-top;
 const uint32_t stream_stride = (src-right - src-left) * 
encoder-format-bpp / 8;
 uint32_t len = stream_stride * stream_height;
-GstBuffer *buffer = gst_buffer_new_and_alloc(len);
 #ifdef HAVE_GSTREAMER_0_10
+GstBuffer *buffer = gst_buffer_new_and_alloc(len);
 uint8_t *b = GST_BUFFER_DATA(buffer);
+uint8_t *dst = b;
 #else
-GstMapInfo map;
-gst_buffer_map(buffer, map, GST_MAP_WRITE);
-uint8_t *b = map.data;
+GstBuffer *buffer = gst_buffer_new();
+GstMapInfo map = { .memory = NULL };
 #endif
-uint8_t *dst = b;
 
 /* Note that we should not reorder the lines, even if top_down is false.
  * It just changes the number of lines to skip at the start of the bitmap.
@@ -315,6 +329,70 @@ static int push_raw_frame(GstEncoder *encoder, const 
SpiceBitmap *bitmap,
 
 if (stream_stride == bitmap-stride) {
 /* We can copy the bitmap chunk by chunk */
+#ifdef DO_ZERO_COPY
+/* We cannot control the lifetime of the bitmap but we can wrap it in
+ * the buffer anyway because:
+ * - Before returning from gst_encoder_encode_frame() we wait for the
+ *   pipeline to have converted this frame into a compressed buffer.
+ *   So it has to have gone through the frame at least once.
+ * - For all encoders but MJPEG, the first element of the pipeline will
+ *   convert the bitmap to another image format which entails copying
+ *   it. So by the time the encoder starts its work, this buffer will
+ *   not be needed anymore.
+ * - The MJPEG encoder does not perform inter-frame compression and 
thus
+ *   does not need to keep hold of this buffer once it has processed 
it.
+ */
+while (chunk_offset = chunks-chunk[chunk].len) {
+/* Make sure that the chunk is not padded */
+if (chunks-chunk[chunk].len % bitmap-stride != 0) {
+gst_buffer_unref(buffer);
+return VIDEO_ENCODER_FRAME_UNSUPPORTED;
+}
+chunk_offset -= chunks-chunk

[Spice-devel] [PATCH 0/12] Add GStreamer support for video streams (take 3)

2015-06-10 Thread Francois Gouget

This follows up on the previous patch series with the following 
main improvements:
- GStreamer 1.0 support.
- Zero-copy support for the input frame.
- H264 support.


This time around I'm only sending the patches needed for the Spice 
server to limit the size of the series. To simplify testing I have put 
the spice-gtk patches on GitHub. Actually all the patches are there on 
their respective 'gst' branches.

spice:  https://github.com/fgouget/spice
spice-gtk:  https://github.com/fgouget/spice-gtk
xf86-video-qxl: https://github.com/fgouget/xf86-video-qxl
spice-common:   https://github.com/fgouget/spice-common
spice-protocol: https://github.com/fgouget/spice-protocol

(there's also 'extras' branches with more experimental/future patches 
for the curious)

For spice-html5 and QEMU one would have to refer to the patches posted 
previously on spice-devel. They should still work with this series.

Let me know if there are changes that are needed for inclusion. 
Otherwise I think the next step is adding proper bitrate control.

-- 
Francois Gouget fgou...@codeweavers.com
___
Spice-devel mailing list
Spice-devel@lists.freedesktop.org
http://lists.freedesktop.org/mailman/listinfo/spice-devel


[Spice-devel] [PATCH spice 1/12] server: Convert a couple of rate control checks into asserts in the mjpeg video encoder. (take 3)

2015-06-10 Thread Francois Gouget
The checks would lead the reader to think these functions can be called when 
bit rate control is off when in fact they are only called when it is active.

Signed-off-by: Francois Gouget fgou...@codeweavers.com
---

This patch stands on its own and I think it makes sense even if the 
remainder of the series is not applied. It seemed ok in round 1 so 
again no change this time around. Let me know if it needs further 
refinements for inclusion.

 server/mjpeg_encoder.c | 9 +++--
 1 file changed, 3 insertions(+), 6 deletions(-)

diff --git a/server/mjpeg_encoder.c b/server/mjpeg_encoder.c
index 12447da..95d841f 100644
--- a/server/mjpeg_encoder.c
+++ b/server/mjpeg_encoder.c
@@ -607,9 +607,7 @@ static void 
mjpeg_encoder_adjust_params_to_bit_rate(MJpegEncoder *encoder)
 uint32_t latency = 0;
 uint32_t src_fps;
 
-if (!encoder-rate_control_is_active) {
-return;
-}
+spice_assert(encoder-rate_control_is_active);
 
 rate_control = encoder-rate_control;
 quality_eval = rate_control-quality_eval_data;
@@ -694,9 +692,8 @@ static void mjpeg_encoder_adjust_fps(MJpegEncoder *encoder, 
uint64_t now)
 MJpegEncoderRateControl *rate_control = encoder-rate_control;
 uint64_t adjusted_fps_time_passed;
 
-if (!encoder-rate_control_is_active) {
-return;
-}
+spice_assert(encoder-rate_control_is_active);
+
 adjusted_fps_time_passed = (now - rate_control-adjusted_fps_start_time) / 
1000 / 1000;
 
 if (!rate_control-during_quality_eval 
-- 
2.1.4

___
Spice-devel mailing list
Spice-devel@lists.freedesktop.org
http://lists.freedesktop.org/mailman/listinfo/spice-devel


[Spice-devel] [PATCH spice 2/12] server: Remove the rate_control_is_active field from MJpegEncoder. (take 3)

2015-06-10 Thread Francois Gouget
It is redundant with the corresponding callbacks.

Signed-off-by: Francois Gouget fgou...@codeweavers.com
---

This patch only depends on the first one and I think it makes sense even 
if the remainder of the series is not applied. It seemed ok in round 1 
so again no change this time around. Let me know if it needs further
refinements for inclusion.


 server/mjpeg_encoder.c | 22 +-
 server/mjpeg_encoder.h |  2 +-
 server/red_worker.c|  4 ++--
 3 files changed, 16 insertions(+), 12 deletions(-)

diff --git a/server/mjpeg_encoder.c b/server/mjpeg_encoder.c
index 95d841f..9a41ef3 100644
--- a/server/mjpeg_encoder.c
+++ b/server/mjpeg_encoder.c
@@ -164,7 +164,6 @@ struct MJpegEncoder {
 unsigned int bytes_per_pixel; /* bytes per pixel of the input buffer */
 void (*pixel_converter)(uint8_t *src, uint8_t *dest);
 
-int rate_control_is_active;
 MJpegEncoderRateControl rate_control;
 MJpegEncoderRateControlCbs cbs;
 void *cbs_opaque;
@@ -185,21 +184,25 @@ static uint32_t get_min_required_playback_delay(uint64_t 
frame_enc_size,
 uint64_t byte_rate,
 uint32_t latency);
 
-MJpegEncoder *mjpeg_encoder_new(int bit_rate_control, uint64_t 
starting_bit_rate,
+static inline int rate_control_is_active(MJpegEncoder* encoder)
+{
+return encoder-cbs.get_roundtrip_ms != NULL;
+}
+
+MJpegEncoder *mjpeg_encoder_new(uint64_t starting_bit_rate,
 MJpegEncoderRateControlCbs *cbs, void *opaque)
 {
 MJpegEncoder *enc;
 
-spice_assert(!bit_rate_control || (cbs  cbs-get_roundtrip_ms  
cbs-get_source_fps));
+spice_assert(!cbs || (cbs  cbs-get_roundtrip_ms  
cbs-get_source_fps));
 
 enc = spice_new0(MJpegEncoder, 1);
 
 enc-first_frame = TRUE;
-enc-rate_control_is_active = bit_rate_control;
 enc-rate_control.byte_rate = starting_bit_rate / 8;
 enc-starting_bit_rate = starting_bit_rate;
 
-if (bit_rate_control) {
+if (cbs) {
 struct timespec time;
 
 clock_gettime(CLOCK_MONOTONIC, time);
@@ -211,6 +214,7 @@ MJpegEncoder *mjpeg_encoder_new(int bit_rate_control, 
uint64_t starting_bit_rate
 enc-rate_control.quality_eval_data.reason = 
MJPEG_QUALITY_EVAL_REASON_RATE_CHANGE;
 enc-rate_control.warmup_start_time = ((uint64_t) time.tv_sec) * 
10 + time.tv_nsec;
 } else {
+enc-cbs.get_roundtrip_ms = NULL;
 mjpeg_encoder_reset_quality(enc, MJPEG_LEGACY_STATIC_QUALITY_ID, 
MJPEG_MAX_FPS, 0);
 }
 
@@ -607,7 +611,7 @@ static void 
mjpeg_encoder_adjust_params_to_bit_rate(MJpegEncoder *encoder)
 uint32_t latency = 0;
 uint32_t src_fps;
 
-spice_assert(encoder-rate_control_is_active);
+spice_assert(rate_control_is_active(encoder));
 
 rate_control = encoder-rate_control;
 quality_eval = rate_control-quality_eval_data;
@@ -692,7 +696,7 @@ static void mjpeg_encoder_adjust_fps(MJpegEncoder *encoder, 
uint64_t now)
 MJpegEncoderRateControl *rate_control = encoder-rate_control;
 uint64_t adjusted_fps_time_passed;
 
-spice_assert(encoder-rate_control_is_active);
+spice_assert(rate_control_is_active(encoder));
 
 adjusted_fps_time_passed = (now - rate_control-adjusted_fps_start_time) / 
1000 / 1000;
 
@@ -734,7 +738,7 @@ int mjpeg_encoder_start_frame(MJpegEncoder *encoder, 
SpiceBitmapFmt format,
 {
 uint32_t quality;
 
-if (encoder-rate_control_is_active) {
+if (rate_control_is_active(encoder)) {
 MJpegEncoderRateControl *rate_control = encoder-rate_control;
 struct timespec time;
 uint64_t now;
@@ -1131,7 +1135,7 @@ void mjpeg_encoder_client_stream_report(MJpegEncoder 
*encoder,
 end_frame_mm_time - start_frame_mm_time,
 end_frame_delay, audio_delay);
 
-if (!encoder-rate_control_is_active) {
+if (!rate_control_is_active(encoder)) {
 spice_debug(rate control was not activated: ignoring);
 return;
 }
diff --git a/server/mjpeg_encoder.h b/server/mjpeg_encoder.h
index 741ea1c..d584b92 100644
--- a/server/mjpeg_encoder.h
+++ b/server/mjpeg_encoder.h
@@ -49,7 +49,7 @@ typedef struct MJpegEncoderStats {
 double avg_quality;
 } MJpegEncoderStats;
 
-MJpegEncoder *mjpeg_encoder_new(int bit_rate_control, uint64_t 
starting_bit_rate,
+MJpegEncoder *mjpeg_encoder_new(uint64_t starting_bit_rate,
 MJpegEncoderRateControlCbs *cbs, void *opaque);
 void mjpeg_encoder_destroy(MJpegEncoder *encoder);
 
diff --git a/server/red_worker.c b/server/red_worker.c
index 5deb30b..e0ff8e9 100644
--- a/server/red_worker.c
+++ b/server/red_worker.c
@@ -3100,9 +3100,9 @@ static void 
red_display_create_stream(DisplayChannelClient *dcc, Stream *stream)
 mjpeg_cbs.update_client_playback_delay = 
red_stream_update_client_playback_latency;
 
 initial_bit_rate = red_stream_get_initial_bit_rate(dcc, stream);
-agent

[Spice-devel] [PATCH spice 12/12] server: Add h264 support to the GStreamer video encoder. (take 3b)

2015-06-11 Thread Francois Gouget
Signed-off-by: Francois Gouget fgou...@codeweavers.com
---

Updated so it applies after the VP8 'take 3b' patch.


diff --git a/server/gstreamer_encoder.c b/server/gstreamer_encoder.c
index c638c3e..58c4c7e 100644
--- a/server/gstreamer_encoder.c
+++ b/server/gstreamer_encoder.c
@@ -206,6 +206,9 @@ static gboolean construct_pipeline(GstEncoder *encoder, 
const SpiceBitmap *bitma
 case SPICE_VIDEO_CODEC_TYPE_VP8:
 gstenc_name = vp8enc;
 break;
+case SPICE_VIDEO_CODEC_TYPE_H264:
+gstenc_name = x264enc;
+break;
 default:
 spice_warning(unsupported codec type %d, encoder-base.codec_type);
 return FALSE;
@@ -262,6 +265,17 @@ static gboolean construct_pipeline(GstEncoder *encoder, 
const SpiceBitmap *bitma
  NULL);
 break;
 }
+case SPICE_VIDEO_CODEC_TYPE_H264:
+g_object_set(G_OBJECT(encoder-gstenc),
+ bitrate, encoder-bit_rate / 1024,
+ byte-stream, TRUE,
+ aud, FALSE,
+ tune, 4, /* Zero latency */
+ intra-refresh, TRUE,
+ sliced-threads, TRUE,
+ speed-preset, 1, /* ultrafast */
+ NULL);
+break;
 default:
 spice_warning(unknown encoder type %d, encoder-base.codec_type);
 reset_pipeline(encoder);
@@ -601,7 +615,8 @@ GstEncoder *create_gstreamer_encoder(SpiceVideoCodecType 
codec_type, uint64_t st
 
 spice_assert(!cbs || (cbs  cbs-get_roundtrip_ms  
cbs-get_source_fps));
 if (codec_type != SPICE_VIDEO_CODEC_TYPE_MJPEG 
-codec_type != SPICE_VIDEO_CODEC_TYPE_VP8) {
+codec_type != SPICE_VIDEO_CODEC_TYPE_VP8 
+codec_type != SPICE_VIDEO_CODEC_TYPE_H264) {
 spice_warning(unsupported codec type %d, codec_type);
 return NULL;
 }
diff --git a/server/red_dispatcher.c b/server/red_dispatcher.c
index 08623e2..a034949 100644
--- a/server/red_dispatcher.c
+++ b/server/red_dispatcher.c
@@ -267,12 +267,14 @@ static create_video_encoder_proc video_encoder_procs[] = {
 static const EnumNames video_codec_names[] = {
 {SPICE_VIDEO_CODEC_TYPE_MJPEG, mjpeg},
 {SPICE_VIDEO_CODEC_TYPE_VP8, vp8},
+{SPICE_VIDEO_CODEC_TYPE_H264, h264},
 {0, NULL},
 };
 
 static const EnumNames video_cap_names[] = {
 {SPICE_DISPLAY_CAP_CODEC_MJPEG, mjpeg},
 {SPICE_DISPLAY_CAP_CODEC_VP8, vp8},
+{SPICE_DISPLAY_CAP_CODEC_H264, h264},
 {0, NULL},
 };
 
-- 
2.1.4
___
Spice-devel mailing list
Spice-devel@lists.freedesktop.org
http://lists.freedesktop.org/mailman/listinfo/spice-devel


[Spice-devel] [PATCH spice 7/12] server: Add VP8 support, a video codec preference list and compatibility checks with the Spice client. (take 3b)

2015-06-11 Thread Francois Gouget
The video encoder preferences can be expressed by building a semi-colon 
separated list of
encoder:codec pairs. For instance 'gstreamer:vp8;spice:mjpeg' to pick first the 
GStreamer VP8
video encoder first and used the original MJPEG video encoder one as a fallback.
The server has a default preference list which can also be selected by 
specifying 'auto' as the
preferences list.
The client compatibility check relies on the following new 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, for now MJPEG 
and VP8.

Signed-off-by: Francois Gouget fgou...@codeweavers.com
---

On Thu, 11 Jun 2015, Fabio Fantoni wrote:
[...]
  ../../server/.libs/libspice-server.so: undefined reference to
  `g_get_num_processors'

 toso in spice chat told that was added in glib 2.36check 
pkg-config
 --modversion glib-2.0 (this should probably bump the configure version
 for glib tho)

I think it's better to check directly for the presence of 
g_get_num_processors(). That way it works even if some distribution 
decides to backport it or removes it later on. Here is an updated patch. 
Note that this will impact the GStreamer 1.0 and h264 patches that 
follow.


diff --git a/configure.ac b/configure.ac
index 34e1a4a..ed3a337 100644
--- a/configure.ac
+++ b/configure.ac
@@ -154,6 +154,10 @@ fi
 PKG_CHECK_MODULES([GLIB2], [glib-2.0 = 2.22])
 AS_VAR_APPEND([SPICE_REQUIRES], [ glib-2.0 = 2.22])
 
+AC_CHECK_LIB(glib-2.0, g_get_num_processors,
+ AC_DEFINE([HAVE_G_GET_NUMPROCESSORS], 1, [Defined if we have 
g_get_num_processors()]),,
+ $GLIB2_LIBS)
+
 PKG_CHECK_MODULES(PIXMAN, pixman-1 = 0.17.7)
 AC_SUBST(PIXMAN_CFLAGS)
 AC_SUBST(PIXMAN_LIBS)
diff --git a/server/gstreamer_encoder.c b/server/gstreamer_encoder.c
index 3600b1b..8fa9071 100644
--- a/server/gstreamer_encoder.c
+++ b/server/gstreamer_encoder.c
@@ -178,10 +178,27 @@ static gboolean set_appsrc_caps(GstEncoder *encoder)
 
 static gboolean construct_pipeline(GstEncoder *encoder, const SpiceBitmap 
*bitmap)
 {
+gboolean no_clock = FALSE;
+const gchar* gstenc_name;
+switch (encoder-base.codec_type)
+{
+case SPICE_VIDEO_CODEC_TYPE_MJPEG:
+gstenc_name = ffenc_mjpeg;
+no_clock = TRUE;
+break;
+case SPICE_VIDEO_CODEC_TYPE_VP8:
+gstenc_name = vp8enc;
+break;
+default:
+spice_warning(unsupported codec type %d, encoder-base.codec_type);
+return FALSE;
+}
+
 GError *err = NULL;
-const gchar* desc = appsrc name=src format=2 do-timestamp=true ! 
ffmpegcolorspace ! ffenc_mjpeg name=encoder ! appsink name=sink;
+gchar *desc = g_strdup_printf(appsrc name=src format=2 do-timestamp=true 
! ffmpegcolorspace ! %s name=encoder ! appsink name=sink, gstenc_name);
 spice_debug(GStreamer pipeline: %s, desc);
 encoder-pipeline = gst_parse_launch_full(desc, NULL, 
GST_PARSE_FLAG_FATAL_ERRORS, err);
+g_free(desc);
 if (!encoder-pipeline) {
 spice_warning(GStreamer error: %s, err-message);
 g_clear_error(err);
@@ -191,19 +208,36 @@ static gboolean construct_pipeline(GstEncoder *encoder, 
const SpiceBitmap *bitma
 encoder-gstenc = gst_bin_get_by_name(GST_BIN(encoder-pipeline), 
encoder);
 encoder-appsink = 
GST_APP_SINK(gst_bin_get_by_name(GST_BIN(encoder-pipeline), sink));
 
+/* Set the encoder initial bit rate, and ask for a low latency */
+adjust_bit_rate(encoder);
+g_object_set(G_OBJECT(encoder-gstenc), bitrate, encoder-bit_rate, 
NULL);
+if (encoder-base.codec_type == SPICE_VIDEO_CODEC_TYPE_VP8) {
+/* See http://www.webmproject.org/docs/encoder-parameters/ */
+#ifdef HAVE_G_GET_NUMPROCESSORS
+int core_count = g_get_num_processors();
+#else
+int core_count = 1;
+#endif
+g_object_set(G_OBJECT(encoder-gstenc),
+ mode, 1, /* CBR */
+ max-latency, 0,
+ speed, 7,
+ resize-allowed, TRUE,
+ threads, core_count - 1,
+ NULL);
+   }
+
 /* Set the source caps */
 encoder-src_caps = NULL;
 if (!set_appsrc_caps(encoder)) {
 return FALSE;
 }
 
-/* Set the encoder initial bit rate */
-adjust_bit_rate(encoder);
-g_object_set(G_OBJECT(encoder-gstenc), bitrate, encoder-bit_rate, 
NULL);
-
 /* Start playing */
-spice_debug(removing the pipeline clock);
-gst_pipeline_use_clock(GST_PIPELINE(encoder-pipeline), NULL);
+if (no_clock) {
+spice_debug(removing the pipeline clock);
+gst_pipeline_use_clock(GST_PIPELINE(encoder-pipeline), NULL);
+}
 spice_debug(setting state to PLAYING);
 if (gst_element_set_state(encoder-pipeline, GST_STATE_PLAYING

[Spice-devel] [PATCH spice 10/12] server: Add GStreamer 1.0 support. (take 3b)

2015-06-11 Thread Francois Gouget
Signed-off-by: Francois Gouget fgou...@codeweavers.com
---

Updated so it applies after the new VP8 patch.

diff --git a/configure.ac b/configure.ac
index ed3a337..6a5ddb9 100644
--- a/configure.ac
+++ b/configure.ac
@@ -92,14 +92,32 @@ if test x$enable_smartcard = xyes; then
 fi
 
 AC_ARG_ENABLE(gstreamer,
-  AS_HELP_STRING([--enable-gstreamer=@:@auto/yes/no@:@],
- [Enable GStreamer 0.10 support]),
+  AS_HELP_STRING([--enable-gstreamer=@:@auto/0.10/1.0/yes/no@:@],
+ [Enable GStreamer support]),
   [],
   [enable_gstreamer=auto])
 
-if test x$enable_gstreamer != xno; then
+if test x$enable_gstreamer != xno  test x$enable_gstreamer != x0.10; 
then
+PKG_CHECK_MODULES(GSTREAMER_1_0, [gstreamer-1.0, gstreamer-app-1.0],
+  [enable_gstreamer=1.0
+   have_gstreamer_1_0=yes],
+  [have_gstreamer_1_0=no])
+if test x$have_gstreamer_1_0 = xyes; then
+AC_SUBST(GSTREAMER_1_0_CFLAGS)
+AC_SUBST(GSTREAMER_1_0_LIBS)
+AS_VAR_APPEND([SPICE_REQUIRES], [ gstreamer-1.0 gstreamer-app-1.0])
+AC_DEFINE([HAVE_GSTREAMER_1_0], [1], [Define if supporting GStreamer 
1.0])
+elif test x$enable_gstreamer = x1.0; then
+AC_MSG_ERROR([GStreamer 1.0 support requested but not found. You may 
set GSTREAMER_1_0_CFLAGS and GSTREAMER_1_0_LIBS to avoid the need to call 
pkg-config.])
+fi
+else
+have_gstreamer_1_0=no
+fi
+AM_CONDITIONAL(SUPPORT_GSTREAMER_1_0, test x$have_gstreamer_1_0 = xyes)
+
+if test x$enable_gstreamer != xno  test x$enable_gstreamer != x1.0; 
then
 PKG_CHECK_MODULES(GSTREAMER_0_10, [gstreamer-0.10, gstreamer-app-0.10],
-  [enable_gstreamer=yes
+  [enable_gstreamer=0.10
have_gstreamer_0_10=yes],
   [have_gstreamer_0_10=no])
 if test x$have_gstreamer_0_10 = xyes; then
@@ -107,7 +125,7 @@ if test x$enable_gstreamer != xno; then
 AC_SUBST(GSTREAMER_0_10_LIBS)
 AS_VAR_APPEND([SPICE_REQUIRES], [ gstreamer-0.10 gstreamer-app-0.10])
 AC_DEFINE([HAVE_GSTREAMER_0_10], [1], [Define if supporting GStreamer 
0.10])
-elif test x$enable_gstreamer = xyes; then
+elif test x$enable_gstreamer = x0.10; then
 AC_MSG_ERROR([GStreamer 0.10 support requested but not found. You may 
set GSTREAMER_0_10_CFLAGS and GSTREAMER_0_10_LIBS to avoid the need to call 
pkg-config.])
 fi
 else
@@ -115,6 +133,11 @@ else
 fi
 AM_CONDITIONAL(SUPPORT_GSTREAMER_0_10, test x$have_gstreamer_0_10 = xyes)
 
+if test x$enable_gstreamer = xyes; then
+AC_MSG_ERROR(GStreamer support requested but not found)
+fi
+AS_IF([test x$enable_gstreamer = xauto], [enable_gstreamer=no])
+
 AC_ARG_ENABLE(automated_tests,
 [  --enable-automated-tests Enable automated tests using spicy-screenshot 
(part of spice--gtk)],,
 [enable_automated_tests=no])
@@ -386,7 +409,7 @@ echo 
 
 Smartcard:${enable_smartcard}
 
-GStreamer 0.10:   ${have_gstreamer_0_10}
+GStreamer:${enable_gstreamer}
 
 SASL support: ${enable_sasl}
 
diff --git a/server/Makefile.am b/server/Makefile.am
index 4921bc3..9fb0c8e 100644
--- a/server/Makefile.am
+++ b/server/Makefile.am
@@ -12,6 +12,7 @@ AM_CPPFLAGS = \
$(SLIRP_CFLAGS) \
$(SMARTCARD_CFLAGS) \
$(GSTREAMER_0_10_CFLAGS)\
+   $(GSTREAMER_1_0_CFLAGS) \
$(SSL_CFLAGS)   \
$(VISIBILITY_HIDDEN_CFLAGS) \
$(WARN_CFLAGS)  \
@@ -42,7 +43,8 @@ libspice_server_la_LIBADD =   
\
$(PIXMAN_LIBS)  \
$(SASL_LIBS)\
$(SLIRP_LIBS)   \
-   $(GSTREAMER_0_10_LIBS)  
\
+   $(GSTREAMER_0_10_LIBS)  \
+   $(GSTREAMER_1_0_LIBS)   \
$(SSL_LIBS) \
$(Z_LIBS)   \
$(SPICE_NONPKGCONFIG_LIBS)  \
@@ -142,7 +144,13 @@ endif
 
 if SUPPORT_GSTREAMER_0_10
 libspice_server_la_SOURCES +=  \
-   gstreamer_encoder.c \
+   gstreamer_encoder.c \
+   $(NULL)
+endif
+
+if SUPPORT_GSTREAMER_1_0
+libspice_server_la_SOURCES +=  \
+   gstreamer_encoder.c \
$(NULL)
 endif
 
diff --git a/server/gstreamer_encoder.c b/server/gstreamer_encoder.c
index 8fa9071..0743879 100644
--- a/server

[Spice-devel] [PATCH protocol 6/12] Add support for the VP8 and H264 video codecs and for advertising supported video codecs. (take 3)

2015-06-10 Thread Francois Gouget
Clients that support multiple codecs should advertise the 
SPICE_DISPLAY_CAP_MULTI_CODEC capability and one SPICE_DISPLAY_CAP_CODEC_XXX 
per supported codec.

Signed-off-by: Francois Gouget fgou...@codeweavers.com
---

This should be followed by a spice-common commit that ensures we get the 
right version of these headers.

Changes since take 2:
- This patch also adds h264.

 spice/enums.h| 2 ++
 spice/protocol.h | 4 
 2 files changed, 6 insertions(+)

diff --git a/spice/enums.h b/spice/enums.h
index 18e2f74..2bb2739 100644
--- a/spice/enums.h
+++ b/spice/enums.h
@@ -139,6 +139,8 @@ typedef enum SpicePathFlags {
 
 typedef enum SpiceVideoCodecType {
 SPICE_VIDEO_CODEC_TYPE_MJPEG = 1,
+SPICE_VIDEO_CODEC_TYPE_VP8,
+SPICE_VIDEO_CODEC_TYPE_H264,
 
 SPICE_VIDEO_CODEC_TYPE_ENUM_END
 } SpiceVideoCodecType;
diff --git a/spice/protocol.h b/spice/protocol.h
index bea376c..d53642a 100644
--- a/spice/protocol.h
+++ b/spice/protocol.h
@@ -134,6 +134,10 @@ enum {
 SPICE_DISPLAY_CAP_A8_SURFACE,
 SPICE_DISPLAY_CAP_STREAM_REPORT,
 SPICE_DISPLAY_CAP_LZ4_COMPRESSION,
+SPICE_DISPLAY_CAP_MULTI_CODEC,
+SPICE_DISPLAY_CAP_CODEC_MJPEG,
+SPICE_DISPLAY_CAP_CODEC_VP8,
+SPICE_DISPLAY_CAP_CODEC_H264,
 };
 
 enum {
-- 
2.1.4
___
Spice-devel mailing list
Spice-devel@lists.freedesktop.org
http://lists.freedesktop.org/mailman/listinfo/spice-devel


[Spice-devel] [PATCH qxl 8/12] spiceqxl: Add SpiceVideoCodecs and $XSPICE_VIDEO_CODECS for specifying video codec preferences. (take 3)

2015-06-10 Thread Francois Gouget

Signed-off-by: Francois Gouget fgou...@codeweavers.com
---

Changes since take 1:
- Fixed a brace placement.


 examples/spiceqxl.xorg.conf.example |  7 +++
 src/qxl.h   |  1 +
 src/qxl_driver.c|  2 ++
 src/spiceqxl_spice_server.c | 15 +++
 4 files changed, 25 insertions(+)

diff --git a/examples/spiceqxl.xorg.conf.example 
b/examples/spiceqxl.xorg.conf.example
index d15f7f2..a82c2be 100644
--- a/examples/spiceqxl.xorg.conf.example
+++ b/examples/spiceqxl.xorg.conf.example
@@ -51,6 +51,13 @@ Section Device
 # defaults to filter.
 #Option SpiceStreamingVideo 
 
+# Set video codecs to use.  Provide a semicolon list of
+# codecs, in preference order.  Each codec requires an encoder
+# which can be one of spice or gstreamer, and then a codec type,
+# for instance mjpeg or vp8. The default is spice:mjpeg,
+# which uses the builtin mjpeg encoder.
+#Option SpiceVideoCodecs 
+
 # Set zlib glz wan compression. Options are auto, never, always.
 # defaults to auto.
 #Option SpiceZlibGlzWanCompression 
diff --git a/src/qxl.h b/src/qxl.h
index ff55604..5cc8d05 100644
--- a/src/qxl.h
+++ b/src/qxl.h
@@ -158,6 +158,7 @@ enum {
 OPTION_SURFACE_BUFFER_SIZE,
 OPTION_COMMAND_BUFFER_SIZE,
 OPTION_SPICE_SMARTCARD_FILE,
+OPTION_SPICE_VIDEO_CODECS,
 #endif
 OPTION_COUNT,
 };
diff --git a/src/qxl_driver.c b/src/qxl_driver.c
index ce0a88e..d036dac 100644
--- a/src/qxl_driver.c
+++ b/src/qxl_driver.c
@@ -155,6 +155,8 @@ const OptionInfoRec DefaultOptions[] =
   CommandBufferSize,OPTV_INTEGER,
{DEFAULT_COMMAND_BUFFER_SIZE}, FALSE},
 { OPTION_SPICE_SMARTCARD_FILE,
   SpiceSmartcardFile,   OPTV_STRING,{0}, FALSE},
+{ OPTION_SPICE_VIDEO_CODECS,
+  SpiceVideoCodecs, OPTV_STRING,{0}, FALSE},
 #endif
 
 { -1, NULL, OPTV_NONE, {0}, FALSE }
diff --git a/src/spiceqxl_spice_server.c b/src/spiceqxl_spice_server.c
index 14ee752..2f39561 100644
--- a/src/spiceqxl_spice_server.c
+++ b/src/spiceqxl_spice_server.c
@@ -173,6 +173,9 @@ void xspice_set_spice_server_options(OptionInfoPtr options)
 const char *streaming_video =
 get_str_option(options, OPTION_SPICE_STREAMING_VIDEO,
XSPICE_STREAMING_VIDEO);
+const char *video_codecs =
+get_str_option(options, OPTION_SPICE_VIDEO_CODECS,
+   XSPICE_VIDEO_CODECS);
 int agent_mouse =
 get_bool_option(options, OPTION_SPICE_AGENT_MOUSE,
 XSPICE_AGENT_MOUSE);
@@ -295,6 +298,18 @@ void xspice_set_spice_server_options(OptionInfoPtr options)
 spice_server_set_streaming_video(spice_server, streaming_video_opt);
 }
 
+if (video_codecs) {
+#if SPICE_SERVER_VERSION = 0x000c06 /* 0.12.6 */
+if (spice_server_set_video_codecs(spice_server, video_codecs)) {
+fprintf(stderr, spice: invalid video encoder %s\n, video_codecs);
+exit(1);
+}
+#else
+fprintf(stderr, spice: video_codecs are not available (spice = 
0.12.6 required)\n);
+exit(1);
+#endif
+}
+
 spice_server_set_agent_mouse
 (spice_server, agent_mouse);
 spice_server_set_playback_compression
-- 
2.1.4

___
Spice-devel mailing list
Spice-devel@lists.freedesktop.org
http://lists.freedesktop.org/mailman/listinfo/spice-devel


[Spice-devel] [PATCH qxl 9/12] Xspice: Add a --video-codecs option to specify which encoder:codec to use.

2015-06-10 Thread Francois Gouget

Signed-off-by: Francois Gouget fgou...@codeweavers.com
---

This adds a --video-codecs option to Xspice as an alternative to 
$XSPICE_VIDEO_CODECS and the SpiceVideoCodecs xorg.conf setting.

 scripts/Xspice | 3 ++-
 1 file changed, 2 insertions(+), 1 deletion(-)

diff --git a/scripts/Xspice b/scripts/Xspice
index 281535d..02875f5 100755
--- a/scripts/Xspice
+++ b/scripts/Xspice
@@ -86,6 +86,7 @@ parser.add_argument('--zlib-glz-wan-compression',
 # TODO - sound support
 parser.add_argument('--streaming-video', choices=['off', 'all', 'filter'],
 default='filter', help='filter by default')
+parser.add_argument('--video-codecs', help=Sets a semicolon-separated list of 
preferred video codecs to use. Each takes the form encoder:codec, with 
spice:mjpeg being the default and other options being provided by gstreamer for 
the mjpeg, vp8 and h264 codecs.)
 add_boolean('--ipv4-only')
 add_boolean('--ipv6-only')
 parser.add_argument('--vdagent', action='store_true', dest='vdagent_enabled', 
default=False, help='launch vdagent  vdagentd. They provide clipboard  
resolution automation')
@@ -251,7 +252,7 @@ var_args = ['port', 'tls_port', 'disable_ticketing',
 'x509_key_file', 'x509_key_password',
 'tls_ciphers', 'dh_file', 'password', 'image_compression',
 'jpeg_wan_compression', 'zlib_glz_wan_compression',
-'streaming_video', 'deferred_fps', 'exit_on_disconnect',
+'streaming_video', 'video_codecs', 'deferred_fps', 'exit_on_disconnect',
 'vdagent_enabled', 'vdagent_virtio_path', 'vdagent_uinput_path',
 'vdagent_uid', 'vdagent_gid']
 
-- 
2.1.4
___
Spice-devel mailing list
Spice-devel@lists.freedesktop.org
http://lists.freedesktop.org/mailman/listinfo/spice-devel


[Spice-devel] [PATCH spice 10/12] server: Add GStreamer 1.0 support.

2015-06-10 Thread Francois Gouget

Signed-off-by: Francois Gouget fgou...@codeweavers.com
---

This adds GStreamer 1.0 support!

By default GStreamer 1.0 is used if available, otherwise GStreamer 0.10 
is used and Spice is compiled without GStreamer support as a last 
resort. It's possible to explicitly require a specific Gstreamer version 
with --enable-gstreamer=1.0 and --enable-gstreamer=0.10, or for any 
version with --enable-gstreamer=yes.

If you get an error while building the pipeline for MJPEG, then it 
probably means you need the fix for this bug:
https://bugzilla.gnome.org/show_bug.cgi?id=750398


 configure.ac   | 35 +
 server/Makefile.am | 12 ++--
 server/gstreamer_encoder.c | 77 --
 server/red_dispatcher.c|  2 +-
 4 files changed, 108 insertions(+), 18 deletions(-)

diff --git a/configure.ac b/configure.ac
index 34e1a4a..3fc46f9 100644
--- a/configure.ac
+++ b/configure.ac
@@ -92,14 +92,32 @@ if test x$enable_smartcard = xyes; then
 fi
 
 AC_ARG_ENABLE(gstreamer,
-  AS_HELP_STRING([--enable-gstreamer=@:@auto/yes/no@:@],
- [Enable GStreamer 0.10 support]),
+  AS_HELP_STRING([--enable-gstreamer=@:@auto/0.10/1.0/yes/no@:@],
+ [Enable GStreamer support]),
   [],
   [enable_gstreamer=auto])
 
-if test x$enable_gstreamer != xno; then
+if test x$enable_gstreamer != xno  test x$enable_gstreamer != x0.10; 
then
+PKG_CHECK_MODULES(GSTREAMER_1_0, [gstreamer-1.0, gstreamer-app-1.0],
+  [enable_gstreamer=1.0
+   have_gstreamer_1_0=yes],
+  [have_gstreamer_1_0=no])
+if test x$have_gstreamer_1_0 = xyes; then
+AC_SUBST(GSTREAMER_1_0_CFLAGS)
+AC_SUBST(GSTREAMER_1_0_LIBS)
+AS_VAR_APPEND([SPICE_REQUIRES], [ gstreamer-1.0 gstreamer-app-1.0])
+AC_DEFINE([HAVE_GSTREAMER_1_0], [1], [Define if supporting GStreamer 
1.0])
+elif test x$enable_gstreamer = x1.0; then
+AC_MSG_ERROR([GStreamer 1.0 support requested but not found. You may 
set GSTREAMER_1_0_CFLAGS and GSTREAMER_1_0_LIBS to avoid the need to call 
pkg-config.])
+fi
+else
+have_gstreamer_1_0=no
+fi
+AM_CONDITIONAL(SUPPORT_GSTREAMER_1_0, test x$have_gstreamer_1_0 = xyes)
+
+if test x$enable_gstreamer != xno  test x$enable_gstreamer != x1.0; 
then
 PKG_CHECK_MODULES(GSTREAMER_0_10, [gstreamer-0.10, gstreamer-app-0.10],
-  [enable_gstreamer=yes
+  [enable_gstreamer=0.10
have_gstreamer_0_10=yes],
   [have_gstreamer_0_10=no])
 if test x$have_gstreamer_0_10 = xyes; then
@@ -107,7 +125,7 @@ if test x$enable_gstreamer != xno; then
 AC_SUBST(GSTREAMER_0_10_LIBS)
 AS_VAR_APPEND([SPICE_REQUIRES], [ gstreamer-0.10 gstreamer-app-0.10])
 AC_DEFINE([HAVE_GSTREAMER_0_10], [1], [Define if supporting GStreamer 
0.10])
-elif test x$enable_gstreamer = xyes; then
+elif test x$enable_gstreamer = x0.10; then
 AC_MSG_ERROR([GStreamer 0.10 support requested but not found. You may 
set GSTREAMER_0_10_CFLAGS and GSTREAMER_0_10_LIBS to avoid the need to call 
pkg-config.])
 fi
 else
@@ -115,6 +133,11 @@ else
 fi
 AM_CONDITIONAL(SUPPORT_GSTREAMER_0_10, test x$have_gstreamer_0_10 = xyes)
 
+if test x$enable_gstreamer = xyes; then
+AC_MSG_ERROR(GStreamer support requested but not found)
+fi
+AS_IF([test x$enable_gstreamer = xauto], [enable_gstreamer=no])
+
 AC_ARG_ENABLE(automated_tests,
 [  --enable-automated-tests Enable automated tests using spicy-screenshot 
(part of spice--gtk)],,
 [enable_automated_tests=no])
@@ -382,7 +405,7 @@ echo 
 
 Smartcard:${enable_smartcard}
 
-GStreamer 0.10:   ${have_gstreamer_0_10}
+GStreamer:${enable_gstreamer}
 
 SASL support: ${enable_sasl}
 
diff --git a/server/Makefile.am b/server/Makefile.am
index 4921bc3..9fb0c8e 100644
--- a/server/Makefile.am
+++ b/server/Makefile.am
@@ -12,6 +12,7 @@ AM_CPPFLAGS = \
$(SLIRP_CFLAGS) \
$(SMARTCARD_CFLAGS) \
$(GSTREAMER_0_10_CFLAGS)\
+   $(GSTREAMER_1_0_CFLAGS) \
$(SSL_CFLAGS)   \
$(VISIBILITY_HIDDEN_CFLAGS) \
$(WARN_CFLAGS)  \
@@ -42,7 +43,8 @@ libspice_server_la_LIBADD =   
\
$(PIXMAN_LIBS)  \
$(SASL_LIBS)\
$(SLIRP_LIBS)   \
-   $(GSTREAMER_0_10_LIBS)  
\
+   $(GSTREAMER_0_10_LIBS

Re: [Spice-devel] [PATCH 0/11] Add GStreamer and VP8 support

2015-05-28 Thread Francois Gouget
On Thu, 28 May 2015, Fabio Fantoni wrote:
[...]
 Thanks for reply, I'm preparing spice-gtk with vp8 patches armhf for
 test it on arm thin client (for example raspberry 2), I want try to use
 gst-omx for hardware decoding of mjpeg and vp8, can I simply build and
 install gst-omx instead of gst-ffmpeg or a change in spice-gtk is needed
 for use gst-omx?

I have patches that could probably be useful to you for this: a 
simplification of the pipeline creation, optionally the use of 
decoebin, and for the performance aspects zero-copy for both the input 
buffer and the ouput frame. So I have created some github repositories 
to make it easier to get these:


https://github.com/fgouget/spice-gtk.git
 * gst branch
   All the above except for decodebin.

 * decodebin branch
   Uses decodebin instead of manually picking the decoders. However on 
   my machine decodebin tries to use vaapi which, given my test 
   configuration, immediately triggers an assert, thus killing the 
   process. Uninstalling vaapi fixes that but it's annoying. So I don't 
   really like the decodebin approach though it's probably more a vaapi 
   bug than a decodebin issue.


https://github.com/fgouget/spice.git
 * gst branch
   The patches adding GStreamer and VP8 support.

 * gst-1.0 branch
   Experimental branch with non-functional GStreamer 1.0 and h264 code. 
   Note that GStreamer 1.0 support can be disabled using './configure 
   --disable-gstreamer-1.0' so H264 support can be tested too.


https://github.com/fgouget/xf86-video-qxl.git
 * gst branch
   Has the patch to make it possible to specify the encoder:codec 
   pairs in either SpiceVideoCodecs or XSPICE_VIDEO_CODECS.


There are also spice-common and spice-protocol repositories but these 
should get pulled automatically.


-- 
Francois Gouget fgou...@codeweavers.com
___
Spice-devel mailing list
Spice-devel@lists.freedesktop.org
http://lists.freedesktop.org/mailman/listinfo/spice-devel


Re: [Spice-devel] [PATCH 0/11] Add GStreamer and VP8 support

2015-05-29 Thread Francois Gouget
On Fri, 29 May 2015, Fabio Fantoni wrote:
[...]
 I'm trying the gst1 support but build fails with this error:
 gstreamer_encoder.c: In function 'construct_pipeline':
 gstreamer_encoder.c:219:41: error: 'GstEncoder' has no member named 'frc'
   deadline, encoder-frc.period * 1000 / 2,
 
 Why you tell that 1.0 is not functional? I suppose not only for the
 build error I had.

It's a merge bug. Sorry. I have pushed an update that fixes this so you 
may want to rebase.

The initial push had caps issues, mostly it was missing format=BGRx, 
which caused GStreamer 1.0 not to work. Note that the failure mode 
caused the video to be sent through the regular non-stream channel so it 
looked like it worked.

Now the GStreamer 1.0 situation is as follows:
 * VP8 works.
 * MJPEG fails because of a caps negotiation error despite the 
   videoconvert element.
 * H264 seems to work but the client fails to display it. So I'm not 
   totally sure.

Also I finally found the right parameters to improve the VP8 encoder 
performance.

Cheers,

-- 
Francois Gouget fgou...@codeweavers.com
___
Spice-devel mailing list
Spice-devel@lists.freedesktop.org
http://lists.freedesktop.org/mailman/listinfo/spice-devel


Re: [Spice-devel] [PATCH 0/11] Add GStreamer and VP8 support

2015-06-01 Thread Francois Gouget
On Mon, 1 Jun 2015, Fabio Fantoni wrote:
[...]
 I suppose that these warning I saw on client are related:
 http://pastebin.com/GeTPyscG
  0:00:00.150227452 27501  0x29f98f0 WARNvideodecoder
  gstvideodecoder.c:2026:gst_video_decoder_chain:vp8dec0 Received
  buffer without a new-segment. Assuming timestamps start from 0.
  0:00:02.889876193 27501  0x29f9ed0 WARNvideodecoder
  gstvideodecoder.c:2026:gst_video_decoder_chain:vp8dec1 Received
  buffer without a new-segment. Assuming timestamps start from 0.

It would be cleaner not to have these warnings (and I'll try to fix 
them), but I don't think they can cause display artifacts.

What kind of video application are you using for testing? Flash/YouTube? 
A local file with a media application like mplayer?


-- 
Francois Gouget fgou...@codeweavers.com
___
Spice-devel mailing list
Spice-devel@lists.freedesktop.org
http://lists.freedesktop.org/mailman/listinfo/spice-devel


[Spice-devel] [PATCH spice 3/7] server: Refactor the Spice server video encoding so alternative implementations can be added. (take 2)

2015-05-27 Thread Francois Gouget
) {
 agent-frames--;
 #ifdef STREAM_STATS
@@ -8603,33 +8539,29 @@ static inline int 
red_marshall_stream_data(RedChannelClient *rcc,
 frame_mm_time =  drawable-red_drawable-mm_time ?
 drawable-red_drawable-mm_time :
 reds_get_mm_time();
+
 outbuf_size = dcc-send_data.stream_outbuf_size;
-ret = mjpeg_encoder_start_frame(agent-mjpeg_encoder, 
image-u.bitmap.format,
-width, height,
-dcc-send_data.stream_outbuf,
-outbuf_size,
-frame_mm_time);
+ret = agent-video_encoder-encode_frame(agent-video_encoder,
+image-u.bitmap, width, height,
+drawable-red_drawable-u.copy.src_area,
+stream-top_down, frame_mm_time,
+dcc-send_data.stream_outbuf, outbuf_size, n);
+
 switch (ret) {
-case MJPEG_ENCODER_FRAME_DROP:
-spice_assert(dcc-use_mjpeg_encoder_rate_control);
+case VIDEO_ENCODER_FRAME_DROP:
+spice_assert(dcc-use_video_encoder_rate_control);
 #ifdef STREAM_STATS
 agent-stats.num_drops_fps++;
 #endif
 return TRUE;
-case MJPEG_ENCODER_FRAME_UNSUPPORTED:
+case VIDEO_ENCODER_FRAME_UNSUPPORTED:
 return FALSE;
-case MJPEG_ENCODER_FRAME_ENCODE_START:
+case VIDEO_ENCODER_FRAME_ENCODE_DONE:
 break;
 default:
-spice_error(bad return value (%d) from mjpeg_encoder_start_frame, 
ret);
-return FALSE;
-}
-
-if (!encode_frame(dcc, drawable-red_drawable-u.copy.src_area,
-  image-u.bitmap, stream)) {
+spice_error(bad return value (%d) from VideoEncoder::encode_frame, 
ret);
 return FALSE;
 }
-n = mjpeg_encoder_end_frame(agent-mjpeg_encoder);
 dcc-send_data.stream_outbuf_size = outbuf_size;
 
 if (!drawable-sized_stream) {
@@ -10255,7 +10187,7 @@ static int 
display_channel_handle_stream_report(DisplayChannelClient *dcc,
 return FALSE;
 }
 stream_agent = dcc-stream_agents[stream_report-stream_id];
-if (!stream_agent-mjpeg_encoder) {
+if (!stream_agent-video_encoder) {
 spice_info(stream_report: no encoder for stream id %u.
 Probably the stream has been destroyed, 
stream_report-stream_id);
 return TRUE;
@@ -10266,7 +10198,7 @@ static int 
display_channel_handle_stream_report(DisplayChannelClient *dcc,
   stream_agent-report_id, stream_report-unique_id);
 return TRUE;
 }
-mjpeg_encoder_client_stream_report(stream_agent-mjpeg_encoder,
+
stream_agent-video_encoder-client_stream_report(stream_agent-video_encoder,
stream_report-num_frames,
stream_report-num_drops,
stream_report-start_frame_mm_time,
diff --git a/server/video_encoder.h b/server/video_encoder.h
new file mode 100644
index 000..d07138b
--- /dev/null
+++ b/server/video_encoder.h
@@ -0,0 +1,162 @@
+/* -*- Mode: C; c-basic-offset: 4; indent-tabs-mode: nil -*- */
+/*
+   Copyright (C) 2009 Red Hat, Inc.
+   Copyright (C) 2015 Jeremy White
+   Copyright (C) 2015 Francois Gouget
+
+   This library is free software; you can redistribute it and/or
+   modify it under the terms of the GNU Lesser General Public
+   License as published by the Free Software Foundation; either
+   version 2.1 of the License, or (at your option) any later version.
+
+   This library is distributed in the hope that it will be useful,
+   but WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+   Lesser General Public License for more details.
+
+   You should have received a copy of the GNU Lesser General Public
+   License along with this library; if not, see A 
HREF=http://www.gnu.org/licenses/;http://www.gnu.org/licenses//A.
+*/
+
+#ifndef _H_video_encoder
+#define _H_video_encoder
+
+#include red_common.h
+
+enum {
+VIDEO_ENCODER_FRAME_UNSUPPORTED = -1,
+VIDEO_ENCODER_FRAME_DROP,
+VIDEO_ENCODER_FRAME_ENCODE_DONE,
+};
+
+typedef struct VideoEncoderStats {
+uint64_t starting_bit_rate;
+uint64_t cur_bit_rate;
+double avg_quality;
+} VideoEncoderStats;
+
+typedef struct VideoEncoder VideoEncoder;
+#ifndef VIDEO_ENCODER_T
+# define VIDEO_ENCODER_T VideoEncoder
+#endif
+
+struct VideoEncoder {
+/* Releases the video encoder's resources */
+void (*destroy)(VIDEO_ENCODER_T *encoder);
+
+/* Compresses the specified src image area into the outbuf buffer.
+ *
+ * @encoder:   The video encoder.
+ * @bitmap:The Spice screen.
+ * @width: The width of the video area. This always matches src.
+ * @height:The height of the video area. This always matches src.
+ * @src:   A rectangle specifying the area occupied by the video.
+ * @top_down:  If true

[Spice-devel] [PATCH spice 2/7] server: Remove the rate_control_is_active field from MJpegEncoder. (take 2)

2015-05-27 Thread Francois Gouget
It is redundant with the corresponding callbacks.
---

As far as I can tell this patch was ok in the previous round so no 
change this time around.

 server/mjpeg_encoder.c | 22 +-
 server/mjpeg_encoder.h |  2 +-
 server/red_worker.c|  4 ++--
 3 files changed, 16 insertions(+), 12 deletions(-)

diff --git a/server/mjpeg_encoder.c b/server/mjpeg_encoder.c
index 95d841f..9a41ef3 100644
--- a/server/mjpeg_encoder.c
+++ b/server/mjpeg_encoder.c
@@ -164,7 +164,6 @@ struct MJpegEncoder {
 unsigned int bytes_per_pixel; /* bytes per pixel of the input buffer */
 void (*pixel_converter)(uint8_t *src, uint8_t *dest);
 
-int rate_control_is_active;
 MJpegEncoderRateControl rate_control;
 MJpegEncoderRateControlCbs cbs;
 void *cbs_opaque;
@@ -185,21 +184,25 @@ static uint32_t get_min_required_playback_delay(uint64_t 
frame_enc_size,
 uint64_t byte_rate,
 uint32_t latency);
 
-MJpegEncoder *mjpeg_encoder_new(int bit_rate_control, uint64_t 
starting_bit_rate,
+static inline int rate_control_is_active(MJpegEncoder* encoder)
+{
+return encoder-cbs.get_roundtrip_ms != NULL;
+}
+
+MJpegEncoder *mjpeg_encoder_new(uint64_t starting_bit_rate,
 MJpegEncoderRateControlCbs *cbs, void *opaque)
 {
 MJpegEncoder *enc;
 
-spice_assert(!bit_rate_control || (cbs  cbs-get_roundtrip_ms  
cbs-get_source_fps));
+spice_assert(!cbs || (cbs  cbs-get_roundtrip_ms  
cbs-get_source_fps));
 
 enc = spice_new0(MJpegEncoder, 1);
 
 enc-first_frame = TRUE;
-enc-rate_control_is_active = bit_rate_control;
 enc-rate_control.byte_rate = starting_bit_rate / 8;
 enc-starting_bit_rate = starting_bit_rate;
 
-if (bit_rate_control) {
+if (cbs) {
 struct timespec time;
 
 clock_gettime(CLOCK_MONOTONIC, time);
@@ -211,6 +214,7 @@ MJpegEncoder *mjpeg_encoder_new(int bit_rate_control, 
uint64_t starting_bit_rate
 enc-rate_control.quality_eval_data.reason = 
MJPEG_QUALITY_EVAL_REASON_RATE_CHANGE;
 enc-rate_control.warmup_start_time = ((uint64_t) time.tv_sec) * 
10 + time.tv_nsec;
 } else {
+enc-cbs.get_roundtrip_ms = NULL;
 mjpeg_encoder_reset_quality(enc, MJPEG_LEGACY_STATIC_QUALITY_ID, 
MJPEG_MAX_FPS, 0);
 }
 
@@ -607,7 +611,7 @@ static void 
mjpeg_encoder_adjust_params_to_bit_rate(MJpegEncoder *encoder)
 uint32_t latency = 0;
 uint32_t src_fps;
 
-spice_assert(encoder-rate_control_is_active);
+spice_assert(rate_control_is_active(encoder));
 
 rate_control = encoder-rate_control;
 quality_eval = rate_control-quality_eval_data;
@@ -692,7 +696,7 @@ static void mjpeg_encoder_adjust_fps(MJpegEncoder *encoder, 
uint64_t now)
 MJpegEncoderRateControl *rate_control = encoder-rate_control;
 uint64_t adjusted_fps_time_passed;
 
-spice_assert(encoder-rate_control_is_active);
+spice_assert(rate_control_is_active(encoder));
 
 adjusted_fps_time_passed = (now - rate_control-adjusted_fps_start_time) / 
1000 / 1000;
 
@@ -734,7 +738,7 @@ int mjpeg_encoder_start_frame(MJpegEncoder *encoder, 
SpiceBitmapFmt format,
 {
 uint32_t quality;
 
-if (encoder-rate_control_is_active) {
+if (rate_control_is_active(encoder)) {
 MJpegEncoderRateControl *rate_control = encoder-rate_control;
 struct timespec time;
 uint64_t now;
@@ -1131,7 +1135,7 @@ void mjpeg_encoder_client_stream_report(MJpegEncoder 
*encoder,
 end_frame_mm_time - start_frame_mm_time,
 end_frame_delay, audio_delay);
 
-if (!encoder-rate_control_is_active) {
+if (!rate_control_is_active(encoder)) {
 spice_debug(rate control was not activated: ignoring);
 return;
 }
diff --git a/server/mjpeg_encoder.h b/server/mjpeg_encoder.h
index 741ea1c..d584b92 100644
--- a/server/mjpeg_encoder.h
+++ b/server/mjpeg_encoder.h
@@ -49,7 +49,7 @@ typedef struct MJpegEncoderStats {
 double avg_quality;
 } MJpegEncoderStats;
 
-MJpegEncoder *mjpeg_encoder_new(int bit_rate_control, uint64_t 
starting_bit_rate,
+MJpegEncoder *mjpeg_encoder_new(uint64_t starting_bit_rate,
 MJpegEncoderRateControlCbs *cbs, void *opaque);
 void mjpeg_encoder_destroy(MJpegEncoder *encoder);
 
diff --git a/server/red_worker.c b/server/red_worker.c
index 5deb30b..e0ff8e9 100644
--- a/server/red_worker.c
+++ b/server/red_worker.c
@@ -3100,9 +3100,9 @@ static void 
red_display_create_stream(DisplayChannelClient *dcc, Stream *stream)
 mjpeg_cbs.update_client_playback_delay = 
red_stream_update_client_playback_latency;
 
 initial_bit_rate = red_stream_get_initial_bit_rate(dcc, stream);
-agent-mjpeg_encoder = mjpeg_encoder_new(TRUE, initial_bit_rate, 
mjpeg_cbs, agent);
+agent-mjpeg_encoder = mjpeg_encoder_new(initial_bit_rate, mjpeg_cbs, 
agent);
 } else {
-

[Spice-devel] [PATCH common 5/7] Add support for the VP8 video codec. (take 2)

2015-05-27 Thread Francois Gouget
---

Thanks to Fabio Fantoni for noticing that spice.proto needed updating 
too. I think I did not notice the issue because the top-level autogen.sh 
keeps rechecking out spice-protocol so spice-protocol/spice/enums.h 
ended up always being newer than spice.proto.

 spice.proto | 1 +
 1 file changed, 1 insertion(+)

diff --git a/spice.proto b/spice.proto
index 01493c9..ecc6308 100644
--- a/spice.proto
+++ b/spice.proto
@@ -329,6 +329,7 @@ flags8 path_flags { /* TODO: C enum names changes */
 
 enum8 video_codec_type {
 MJPEG = 1,
+VP8,
 };
 
 flags8 stream_flags {
-- 
2.1.4
___
Spice-devel mailing list
Spice-devel@lists.freedesktop.org
http://lists.freedesktop.org/mailman/listinfo/spice-devel


[Spice-devel] [PATCH spice 7/7] server: Add VP8 support, a video codec preference list and compatibility checks with the Spice client. (take 2)

2015-05-27 Thread Francois Gouget
;
+static RedVideoCodec new_codecs[RED_MAX_VIDEO_CODECS];
+int count;
+const char* c;
 
-if (num_renderers == RED_MAX_RENDERERS || !(inf = find_renderer(name))) {
-return FALSE;
+if (strcmp(codecs, auto) == 0)
+codecs = VIDEO_ENCODER_DEFAULT_PREFERENCE;
+
+c = codecs;
+count = 0;
+while ( (c = parse_video_codecs(c, encoder_name, codec_name)) ) {
+int convert_failed = FALSE;
+if (count == RED_MAX_VIDEO_CODECS ||
+!name_to_enum(video_encoder_names, encoder_name, encoder) ||
+!name_to_enum(video_codec_names, codec_name, type) ||
+!name_to_enum(video_cap_names, codec_name, cap))
+convert_failed = TRUE;
+
+free(encoder_name);
+free(codec_name);
+
+if (convert_failed)
+return FALSE;
+if (!video_encoder_procs[encoder])
+/* A valid but unsupported video encoder, skip it */
+continue;
+
+new_codecs[count].create = video_encoder_procs[encoder];
+new_codecs[count].type = type;
+new_codecs[count].cap = cap;
+count++;
 }
-renderers[num_renderers++] = inf-id;
+num_video_codecs = count;
+memcpy(video_codecs, new_codecs, sizeof(video_codecs));
 return TRUE;
 }
 
@@ -793,6 +906,22 @@ void red_dispatcher_on_sv_change(void)
 }
 }
 
+void red_dispatcher_on_vc_change(void)
+{
+RedWorkerMessageSetVideoCodecs payload;
+int compression_level = calc_compression_level();
+RedDispatcher *now = dispatchers;
+while (now) {
+now-qxl-st-qif-set_compression_level(now-qxl, compression_level);
+payload.num_video_codecs = num_video_codecs;
+payload.video_codecs = video_codecs;
+dispatcher_send_message(now-dispatcher,
+RED_WORKER_MESSAGE_SET_VIDEO_CODECS,
+payload);
+now = now-next;
+}
+}
+
 void red_dispatcher_set_mouse_mode(uint32_t mode)
 {
 RedWorkerMessageSetMouseMode payload;
@@ -1094,6 +1223,10 @@ void red_dispatcher_init(QXLInstance *qxl)
 init_data.pending = red_dispatcher-pending;
 init_data.num_renderers = num_renderers;
 memcpy(init_data.renderers, renderers, sizeof(init_data.renderers));
+if (num_video_codecs  0)
+red_dispatcher_set_video_codecs(auto);
+init_data.num_video_codecs = num_video_codecs;
+memcpy(init_data.video_codecs, video_codecs, 
sizeof(init_data.video_codecs));
 
 pthread_mutex_init(red_dispatcher-async_lock, NULL);
 init_data.image_compression = image_compression;
diff --git a/server/red_dispatcher.h b/server/red_dispatcher.h
index 907b7c7..eb3aee4 100644
--- a/server/red_dispatcher.h
+++ b/server/red_dispatcher.h
@@ -22,6 +22,7 @@
 
 struct RedChannelClient;
 struct RedDispatcher;
+typedef struct RedVideoCodec RedVideoCodec;
 typedef struct AsyncCommand AsyncCommand;
 
 void red_dispatcher_init(QXLInstance *qxl);
@@ -29,11 +30,13 @@ void red_dispatcher_init(QXLInstance *qxl);
 void red_dispatcher_set_mm_time(uint32_t);
 void red_dispatcher_on_ic_change(void);
 void red_dispatcher_on_sv_change(void);
+void red_dispatcher_on_vc_change(void);
 void red_dispatcher_set_mouse_mode(uint32_t mode);
 void red_dispatcher_on_vm_stop(void);
 void red_dispatcher_on_vm_start(void);
 int red_dispatcher_count(void);
 int red_dispatcher_add_renderer(const char *name);
+int red_dispatcher_set_video_codecs(const char* codecs);
 uint32_t red_dispatcher_qxl_ram_size(void);
 int red_dispatcher_qxl_count(void);
 void red_dispatcher_async_complete(struct RedDispatcher *, AsyncCommand *);
@@ -174,6 +177,11 @@ typedef struct RedWorkerMessageSetStreamingVideo {
 uint32_t streaming_video;
 } RedWorkerMessageSetStreamingVideo;
 
+typedef struct RedWorkerMessageSetVideoCodecs {
+uint32_t num_video_codecs;
+RedVideoCodec* video_codecs;
+} RedWorkerMessageSetVideoCodecs;
+
 typedef struct RedWorkerMessageSetMouseMode {
 uint32_t mode;
 } RedWorkerMessageSetMouseMode;
diff --git a/server/red_worker.c b/server/red_worker.c
index 19e27c5..b8c2259 100644
--- a/server/red_worker.c
+++ b/server/red_worker.c
@@ -1,6 +1,7 @@
 /* -*- Mode: C; c-basic-offset: 4; indent-tabs-mode: nil -*- */
 /*
Copyright (C) 2009 Red Hat, Inc.
+   Copyright (C) 2015 Francois Gouget
 
This library is free software; you can redistribute it and/or
modify it under the terms of the GNU Lesser General Public
@@ -994,6 +995,8 @@ typedef struct RedWorker {
 uint32_t mouse_mode;
 
 uint32_t streaming_video;
+uint32_t num_video_codecs;
+RedVideoCodec video_codecs[RED_MAX_VIDEO_CODECS];
 Stream streams_buf[NUM_STREAMS];
 Stream *free_streams;
 Ring streams;
@@ -3074,10 +3077,41 @@ static void 
red_stream_update_client_playback_latency(void *opaque, uint32_t del
 main_dispatcher_set_mm_time_latency(agent-dcc-common.base.client, 
agent-dcc-streams_max_latency);
 }
 
+static VideoEncoder* red_display_create_video_encoder

[Spice-devel] [PATCH protocol 6/7] Add support for the VP8 video codec and for advertising supported video codecs. (take 2)

2015-05-27 Thread Francois Gouget
Clients that support multiple codecs should advertise the 
SPICE_DISPLAY_CAP_MULTI_CODEC capability and one SPICE_DISPLAY_CAP_CODEC_XXX 
per supported codec.
---

As far as I can tell this patch was ok in the previous round so no 
change this time around.

 spice/enums.h| 1 +
 spice/protocol.h | 3 +++
 2 files changed, 4 insertions(+)

diff --git a/spice/enums.h b/spice/enums.h
index 18e2f74..14675f9 100644
--- a/spice/enums.h
+++ b/spice/enums.h
@@ -139,6 +139,7 @@ typedef enum SpicePathFlags {
 
 typedef enum SpiceVideoCodecType {
 SPICE_VIDEO_CODEC_TYPE_MJPEG = 1,
+SPICE_VIDEO_CODEC_TYPE_VP8,
 
 SPICE_VIDEO_CODEC_TYPE_ENUM_END
 } SpiceVideoCodecType;
diff --git a/spice/protocol.h b/spice/protocol.h
index bea376c..7f0b322 100644
--- a/spice/protocol.h
+++ b/spice/protocol.h
@@ -134,6 +134,9 @@ enum {
 SPICE_DISPLAY_CAP_A8_SURFACE,
 SPICE_DISPLAY_CAP_STREAM_REPORT,
 SPICE_DISPLAY_CAP_LZ4_COMPRESSION,
+SPICE_DISPLAY_CAP_MULTI_CODEC,
+SPICE_DISPLAY_CAP_CODEC_MJPEG,
+SPICE_DISPLAY_CAP_CODEC_VP8,
 };
 
 enum {
-- 
2.1.4
___
Spice-devel mailing list
Spice-devel@lists.freedesktop.org
http://lists.freedesktop.org/mailman/listinfo/spice-devel


[Spice-devel] [PATCH spice 4/7] server: Add a GStreamer 0.10 MJPEG video encoder and use it by default. (take 2)

2015-05-27 Thread Francois Gouget
The GStreamer video encoder is quite primitive and mostly meant to introduce, 
test and debug the basic infrastructure.
The main limitation is the lack of rate control: the bitrate is set at startup 
and will not react to changes in the network conditions. Still it should work 
fine on LANs.
---

Changes since take 1:
- Use autovideoconvert instead of ffmpegcolorspace.
- The width/height comments are now correct in the previous patch of
  the series.
- Added a comment suggesting to avoid copying the compressed buffer as 
  a future improvement.


 configure.ac   |  18 ++
 server/Makefile.am |   8 +
 server/gstreamer_encoder.c | 440 +
 server/red_worker.c|  11 +-
 server/video_encoder.h |   6 +
 5 files changed, 481 insertions(+), 2 deletions(-)
 create mode 100644 server/gstreamer_encoder.c

diff --git a/configure.ac b/configure.ac
index 7a9fc4b..919bf88 100644
--- a/configure.ac
+++ b/configure.ac
@@ -91,6 +91,15 @@ if test x$enable_smartcard = xyes; then
AC_DEFINE([USE_SMARTCARD], [1], [Define if supporting smartcard proxying])
 fi
 
+AC_ARG_ENABLE(gstreamer-0.10,
+[  --enable-gstreamer-0.10   Enable GStreamer 0.10 support],,
+[enable_gstreamer_0_10=yes])
+AS_IF([test x$enable_gstreamer_0_10 != xno], [enable_gstreamer_0_10=yes])
+AM_CONDITIONAL(SUPPORT_GSTREAMER_0_10, test x$enable_gstreamer_0_10 != xno)
+if test x$enable_gstreamer_0_10 = xyes; then
+   AC_DEFINE([HAVE_GSTREAMER_0_10], [1], [Define if supporting GStreamer 0.10])
+fi
+
 AC_ARG_ENABLE(automated_tests,
 [  --enable-automated-tests Enable automated tests using spicy-screenshot 
(part of spice--gtk)],,
 [enable_automated_tests=no])
@@ -127,6 +136,13 @@ if test x$enable_smartcard = xyes; then
 AS_VAR_APPEND([SPICE_REQUIRES], [ libcacard = 0.1.2])
 fi
 
+if test x$enable_gstreamer_0_10 = xyes; then
+PKG_CHECK_MODULES(GSTREAMER_0_10, [gstreamer-0.10, gstreamer-app-0.10])
+AC_SUBST(GSTREAMER_0_10_LIBS)
+AC_SUBST(GSTREAMER_0_10_CFLAGS)
+AS_VAR_APPEND([SPICE_REQUIRES], [ gstreamer-0.10])
+fi
+
 
 PKG_CHECK_MODULES([GLIB2], [glib-2.0 = 2.22])
 AS_VAR_APPEND([SPICE_REQUIRES], [ glib-2.0 = 2.22])
@@ -359,6 +375,8 @@ echo 
 
 Smartcard:${enable_smartcard}
 
+GStreamer-0.10:   ${enable_gstreamer_0_10}
+
 SASL support: ${enable_sasl}
 
 Automated tests:  ${enable_automated_tests}
diff --git a/server/Makefile.am b/server/Makefile.am
index 36b6d45..28c4a46 100644
--- a/server/Makefile.am
+++ b/server/Makefile.am
@@ -11,6 +11,7 @@ AM_CPPFLAGS = \
$(SASL_CFLAGS)  \
$(SLIRP_CFLAGS) \
$(SMARTCARD_CFLAGS) \
+   $(GSTREAMER_0_10_CFLAGS)\
$(SSL_CFLAGS)   \
$(VISIBILITY_HIDDEN_CFLAGS) \
$(WARN_CFLAGS)  \
@@ -41,6 +42,7 @@ libspice_server_la_LIBADD =   
\
$(PIXMAN_LIBS)  \
$(SASL_LIBS)\
$(SLIRP_LIBS)   \
+   $(GSTREAMER_0_10_LIBS)  
\
$(SSL_LIBS) \
$(Z_LIBS)   \
$(SPICE_NONPKGCONFIG_LIBS)  \
@@ -138,6 +140,12 @@ libspice_server_la_SOURCES +=  \
$(NULL)
 endif
 
+if SUPPORT_GSTREAMER_0_10
+libspice_server_la_SOURCES +=  \
+   gstreamer_encoder.c \
+   $(NULL)
+endif
+
 EXTRA_DIST =   \
glz_encode_match_tmpl.c \
glz_encode_tmpl.c   \
diff --git a/server/gstreamer_encoder.c b/server/gstreamer_encoder.c
new file mode 100644
index 000..cd80cc9
--- /dev/null
+++ b/server/gstreamer_encoder.c
@@ -0,0 +1,440 @@
+/* -*- Mode: C; c-basic-offset: 4; indent-tabs-mode: nil -*- */
+/*
+   Copyright (C) 2015 Jeremy White
+   Copyright (C) 2015 Francois Gouget
+
+   This library is free software; you can redistribute it and/or
+   modify it under the terms of the GNU Lesser General Public
+   License as published by the Free Software Foundation; either
+   version 2.1 of the License, or (at your option) any later version.
+
+   This library is distributed in the hope that it will be useful,
+   but WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+   Lesser General Public License for more details.
+
+   You should have received a copy of the GNU Lesser General Public
+   License along with this library; if not, see A 
HREF=http://www.gnu.org/licenses/;http

Re: [Spice-devel] [PATCH 0/11] Add GStreamer and VP8 support

2015-05-27 Thread Francois Gouget
On Thu, 21 May 2015, Fabio Fantoni wrote:
[...]
 Thanks for improving spice, I tried your patches, I applied the
 spice-gtk, spice-protocol and I updated the git submodule to use right
 spice-protocol but make of spice-common/common generate a new enum.h and
 override the spice-protocol patch failing the spice-gtk build with vp8
 codec undefined.
 Seems that also a spice-common patch (at least in spice.proto) is needed
 but missed in the patch serie posted.

Thanks for pointing this out. I could not see it initially because the 
top-level autogen.sh keeps rechecking out spice-protocol so 
spice-protocol/spice/enums.h ended up always being newer than 
spice.proto. I have added a spice-common patch in the new series.


-- 
Francois Gouget fgou...@free.fr  http://fgouget.free.fr/
A particle is an irreducible representation of the Poincaré Group - Eugene 
Wigner___
Spice-devel mailing list
Spice-devel@lists.freedesktop.org
http://lists.freedesktop.org/mailman/listinfo/spice-devel


[Spice-devel] [PATCH spice] server: Remove an unused structure.

2015-05-27 Thread Francois Gouget
---

This struct was introduced in the first commit, c1b79eb0, about 6 years 
ago, but has never been used. So I think it's safe to remove.

 server/red_dispatcher.c | 10 --
 1 file changed, 10 deletions(-)

diff --git a/server/red_dispatcher.c b/server/red_dispatcher.c
index e8a1347..9d02d20 100644
--- a/server/red_dispatcher.c
+++ b/server/red_dispatcher.c
@@ -69,16 +69,6 @@ struct RedDispatcher {
 QXLDevSurfaceCreate surface_create;
 };
 
-typedef struct RedWorkeState {
-uint8_t *io_base;
-unsigned long phys_delta;
-
-uint32_t x_res;
-uint32_t y_res;
-uint32_t bits;
-uint32_t stride;
-} RedWorkeState;
-
 extern uint32_t streaming_video;
 extern spice_image_compression_t image_compression;
 extern spice_wan_compression_t jpeg_state;
-- 
2.1.4
___
Spice-devel mailing list
Spice-devel@lists.freedesktop.org
http://lists.freedesktop.org/mailman/listinfo/spice-devel


Re: [Spice-devel] [PATCH 0/11] Add GStreamer and VP8 support

2015-05-28 Thread Francois Gouget
On Tue, 26 May 2015, Fabio Fantoni wrote:
[...]
 After din't show gstreamer warning anymore but still have image freeze
 and also spice-gtk crash after open video fullscreen, here the full gdb
 datas:
 http://pastebin.com/idTkZLh0

It looks like the crash happened when trying to access the st-out_frame 
buffer that was set up by stream_gst_data() in the client.

I don't know why that would be the case: as far as I can tell that 
pointer is either valid or NULL; even if we return early from 
push_frame() or pull_frame().

It may not be related to the issue you've run into but the patch below 
should help quite a bit if you try running the client more than a minute 
or two:

diff --git a/gtk/channel-display-gst.c b/gtk/channel-display-gst.c
index b880ce4..9da078a 100644
--- a/gtk/channel-display-gst.c
+++ b/gtk/channel-display-gst.c
@@ -221,6 +221,7 @@ static void pull_frame(display_stream *st)
 
 // TODO seems like poor memory management
 if (gst_memory_map(memory, mem_info, GST_MAP_READ)) {
+g_free(st-out_frame);
 st-out_frame = g_malloc0(mem_info.size);
 memcpy(st-out_frame, mem_info.data, mem_info.size);

I also have a patch that avoids copying the out_frame buffer but given 
the low CPU usage of the client that should not be an issue.


 After I tried with gstreamer using ffmpeg, vp8 doesn't crashed, probably
 was problem of gstreamer0.10-plugins-bad but image freeze problem remain

When does the freeze happen? A short freeze is normal during the 
transition from the regular transport to the video streaming but that 
happens in the mjpeg case too. Is the freeze temporary?


[...]
 About vp8 image freeze here some seconds of gst log debug on spice-gtk
 when problem happen: http://pastebin.com/PP2R43Yf

Nothing jumped at me in this log.


 Using spice:vp8 seems only have low performance.

In my experience the VP8 encoder saturates a core which is why it is not 
smooth. When running a test pipeline through gst-laucnh I'm able to 
solve that by playing with vp8enc's speed and threads parameters but for 
some reason these have no effect in Spice.

gst-launch videotestsrc ! video/x-raw-rgb,width=1024,height=768 ! \
   ffmpegcolorspace ! vp8enc speed=2 threads=4 ! \
   vp8dec ! ffmpegcolorspace ! fpsdisplaysink



-- 
Francois Gouget fgou...@codeweavers.com
___
Spice-devel mailing list
Spice-devel@lists.freedesktop.org
http://lists.freedesktop.org/mailman/listinfo/spice-devel


Re: [Spice-devel] [PATCH 0/11] Add GStreamer and VP8 support

2015-06-02 Thread Francois Gouget
On Tue, 2 Jun 2015, Fabio Fantoni wrote:
[...]
 Video on youtube,

Does it look like the video moves back and forth? Or maybe just the 
progress bar area, with some shearing too. That's a known issue caused 
by the progress bar popping up and down.


 hd trailer (file) with vlc (without vp8 works correctly) and win media 
 player.

I have not been able to really test with VLC here. I use Xspice which 
apparently does not support Xshm and that causes VLC to crash. And since 
I'm not testing with a VM windows media player is out.

Is bandwidth limited between the server and the client? With VP8, if an 
I frame gets dropped then the following P frames will be broken. I'm not 
sure how it handles that. Does adding error-resilient=1 or 
error-resilient=2 to vp8enc make a difference?

-- 
Francois Gouget fgou...@codeweavers.com
___
Spice-devel mailing list
Spice-devel@lists.freedesktop.org
http://lists.freedesktop.org/mailman/listinfo/spice-devel


[Spice-devel] [PATCH spice] HAVE_CLOCK_GETTIME is not used so remove it.

2015-06-11 Thread Francois Gouget
Signed-off-by: Francois Gouget fgou...@codeweavers.com
---

Maybe we should actually use it but currently clock_gettime() uses are 
all over the place and this macro was only used in the client code 
anyway (see 18769714 and 3f3283ee).

 configure.ac | 5 +
 1 file changed, 1 insertion(+), 4 deletions(-)

diff --git a/configure.ac b/configure.ac
index 7a9fc4b..62c714e 100644
--- a/configure.ac
+++ b/configure.ac
@@ -108,10 +108,7 @@ AC_SUBST(COMMON_CFLAGS)
 AC_CHECK_LIBM
 AC_SUBST(LIBM)
 
-AC_CHECK_LIB(rt, clock_gettime,
-   AC_DEFINE([HAVE_CLOCK_GETTIME], 1, [Defined if we have clock_gettime()])
-   LIBRT=-lrt
-   )
+AC_CHECK_LIB(rt, clock_gettime, LIBRT=-lrt)
 AC_SUBST(LIBRT)
 
 AS_VAR_APPEND([SPICE_NONPKGCONFIG_LIBS], [ -pthread $LIBM $LIBRT])
-- 
2.1.4

___
Spice-devel mailing list
Spice-devel@lists.freedesktop.org
http://lists.freedesktop.org/mailman/listinfo/spice-devel


[Spice-devel] [PATCH spice 1/2] server: Refresh the input fps every 5 second, without a timer.

2015-06-11 Thread Francois Gouget
Signed-off-by: Francois Gouget fgou...@codeweavers.com
---

This implements Marc-André Lureau's suggestion:
http://lists.freedesktop.org/archives/spice-devel/2015-June/020202.html

And supersedes the input-fps rounding patch.
http://lists.freedesktop.org/archives/spice-devel/2015-June/020176.html


 server/red_worker.c | 45 +++--
 1 file changed, 15 insertions(+), 30 deletions(-)

diff --git a/server/red_worker.c b/server/red_worker.c
index 5deb30b..a07a78a 100644
--- a/server/red_worker.c
+++ b/server/red_worker.c
@@ -120,7 +120,7 @@
 #define RED_STREAM_GRADUAL_FRAMES_START_CONDITION 0.2
 #define RED_STREAM_FRAMES_RESET_CONDITION 100
 #define RED_STREAM_MIN_SIZE (96 * 96)
-#define RED_STREAM_INPUT_FPS_TIMEOUT (5 * 1000) // 5 sec
+#define RED_STREAM_INPUT_FPS_TIMEOUT ((uint64_t)5 * 1000 * 1000 * 1000) // 5 
sec
 #define RED_STREAM_CHANNEL_CAPACITY 0.8
 /* the client's stream report frequency is the minimum of the 2 values below */
 #define RED_STREAM_CLIENT_REPORT_WINDOW 5 // #frames
@@ -450,9 +450,8 @@ struct Stream {
 Stream *next;
 RingItem link;
 
-SpiceTimer *input_fps_timer;
 uint32_t num_input_frames;
-uint64_t input_fps_timer_start;
+uint64_t input_fps_start_time;
 uint32_t input_fps;
 };
 
@@ -2532,9 +2531,6 @@ static int is_same_drawable(RedWorker *worker, Drawable 
*d1, Drawable *d2)
 
 static inline void red_free_stream(RedWorker *worker, Stream *stream)
 {
-if (stream-input_fps_timer) {
-spice_timer_remove(stream-input_fps_timer);
-}
 stream-next = worker-free_streams;
 worker-free_streams = stream;
 }
@@ -2613,7 +2609,17 @@ static void red_attach_stream(RedWorker *worker, 
Drawable *drawable, Stream *str
 stream-current = drawable;
 drawable-stream = stream;
 stream-last_time = drawable-creation_time;
-stream-num_input_frames++;
+
+uint64_t duration = drawable-creation_time - stream-input_fps_start_time;
+if (duration = RED_STREAM_INPUT_FPS_TIMEOUT) {
+/* Round to the nearest integer, for instance 24 for 23.976 */
+stream-input_fps = ((uint64_t)stream-num_input_frames * 1000 * 1000 
* 1000 + duration / 2) / duration;
+spice_debug(input-fps=%u, stream-input_fps);
+stream-num_input_frames = 0;
+stream-input_fps_start_time = drawable-creation_time;
+} else {
+stream-num_input_frames++;
+}
 
 WORKER_FOREACH_DCC_SAFE(worker, item, next, dcc) {
 StreamAgent *agent;
@@ -3123,24 +3129,6 @@ static void 
red_display_create_stream(DisplayChannelClient *dcc, Stream *stream)
 #endif
 }
 
-static void red_stream_input_fps_timer_cb(void *opaque)
-{
-Stream *stream = opaque;
-uint64_t now = red_now();
-double duration_sec;
-
-spice_assert(opaque);
-if (now == stream-input_fps_timer_start) {
-spice_warning(timer start and expiry time are equal);
-return;
-}
-duration_sec = (now - stream-input_fps_timer_start)/(1000.0*1000*1000);
-stream-input_fps = stream-num_input_frames / duration_sec;
-spice_debug(input-fps=%u, stream-input_fps);
-stream-num_input_frames = 0;
-stream-input_fps_timer_start = now;
-}
-
 static void red_create_stream(RedWorker *worker, Drawable *drawable)
 {
 DisplayChannelClient *dcc;
@@ -3167,12 +3155,9 @@ static void red_create_stream(RedWorker *worker, 
Drawable *drawable)
 SpiceBitmap *bitmap = drawable-red_drawable-u.copy.src_bitmap-u.bitmap;
 stream-top_down = !!(bitmap-flags  SPICE_BITMAP_FLAGS_TOP_DOWN);
 drawable-stream = stream;
-stream-input_fps_timer = 
spice_timer_queue_add(red_stream_input_fps_timer_cb, stream);
-spice_assert(stream-input_fps_timer);
-spice_timer_set(stream-input_fps_timer, RED_STREAM_INPUT_FPS_TIMEOUT);
-stream-num_input_frames = 0;
-stream-input_fps_timer_start = red_now();
 stream-input_fps = MAX_FPS;
+stream-num_input_frames = 0;
+stream-input_fps_start_time = drawable-creation_time;
 worker-streams_size_total += stream-width * stream-height;
 worker-stream_count++;
 WORKER_FOREACH_DCC_SAFE(worker, dcc_ring_item, next, dcc) {
-- 
2.1.4___
Spice-devel mailing list
Spice-devel@lists.freedesktop.org
http://lists.freedesktop.org/mailman/listinfo/spice-devel


[Spice-devel] [PATCH spice 2/2] server: Provide a framerate estimate based on the frames that lead to the stream creation.

2015-06-11 Thread Francois Gouget
This way the video encoder can actually count on a real estimate when it is 
initializing.

Signed-off-by: Francois Gouget fgou...@codeweavers.com
---

Initialisation time is when video encoders need an fps most since they 
have no other information at that point. Yet, all they were getting is 
MAX_FPS (30).

This patch takes advantage of the fact that Spice needs to keep track of 
the related drawables in order to determine whether creating a video 
stream makes sense. So it stores the time of the first drawable and then 
propagates it. So when the time comes to create the stream we can 
provide a framerate estimate based on the first 20 frames. In my tests 
the result falls within one 1 fps of the later estimates and thus is 
much more useful than MAX_FPS.

 server/red_worker.c | 20 
 1 file changed, 16 insertions(+), 4 deletions(-)

diff --git a/server/red_worker.c b/server/red_worker.c
index a07a78a..8374f54 100644
--- a/server/red_worker.c
+++ b/server/red_worker.c
@@ -844,6 +844,7 @@ struct Drawable {
 Ring glz_ring;
 
 red_time_t creation_time;
+red_time_t first_frame_time;
 int frames_count;
 int gradual_frames_count;
 int last_gradual_frame;
@@ -915,6 +916,7 @@ typedef struct RedSurface {
 
 typedef struct ItemTrace {
 red_time_t time;
+red_time_t first_frame_time;
 int frames_count;
 int gradual_frames_count;
 int last_gradual_frame;
@@ -1926,6 +1928,7 @@ static inline void red_add_item_trace(RedWorker *worker, 
Drawable *item)
 
 trace = worker-items_trace[worker-next_item_trace++  ITEMS_TRACE_MASK];
 trace-time = item-creation_time;
+trace-first_frame_time = item-first_frame_time;
 trace-frames_count = item-frames_count;
 trace-gradual_frames_count = item-gradual_frames_count;
 trace-last_gradual_frame = item-last_gradual_frame;
@@ -3155,7 +3158,12 @@ static void red_create_stream(RedWorker *worker, 
Drawable *drawable)
 SpiceBitmap *bitmap = drawable-red_drawable-u.copy.src_bitmap-u.bitmap;
 stream-top_down = !!(bitmap-flags  SPICE_BITMAP_FLAGS_TOP_DOWN);
 drawable-stream = stream;
-stream-input_fps = MAX_FPS;
+/* Provide an fps estimate the video encoder can use when initializing
+ * based on the frames that lead to the creation of the stream. Round to
+ * the nearest integer, for instance 24 for 23.976.
+ */
+uint64_t duration = drawable-creation_time - drawable-first_frame_time;
+stream-input_fps = ((uint64_t)drawable-frames_count * 1000 * 1000 * 1000 
+ duration / 2) / duration;
 stream-num_input_frames = 0;
 stream-input_fps_start_time = drawable-creation_time;
 worker-streams_size_total += stream-width * stream-height;
@@ -3163,9 +3171,9 @@ static void red_create_stream(RedWorker *worker, Drawable 
*drawable)
 WORKER_FOREACH_DCC_SAFE(worker, dcc_ring_item, next, dcc) {
 red_display_create_stream(dcc, stream);
 }
-spice_debug(stream %d %dx%d (%d, %d) (%d, %d), (int)(stream - 
worker-streams_buf), stream-width,
+spice_debug(stream %d %dx%d (%d, %d) (%d, %d) %u fps, (int)(stream - 
worker-streams_buf), stream-width,
 stream-height, stream-dest_area.left, stream-dest_area.top,
-stream-dest_area.right, stream-dest_area.bottom);
+stream-dest_area.right, stream-dest_area.bottom, 
stream-input_fps);
 return;
 }
 
@@ -3419,11 +3427,13 @@ static inline int red_is_stream_start(Drawable 
*drawable)
 // returns whether a stream was created
 static int red_stream_add_frame(RedWorker *worker,
 Drawable *frame_drawable,
+red_time_t first_frame_time,
 int frames_count,
 int gradual_frames_count,
 int last_gradual_frame)
 {
 red_update_copy_graduality(worker, frame_drawable);
+frame_drawable-first_frame_time = first_frame_time;
 frame_drawable-frames_count = frames_count + 1;
 frame_drawable-gradual_frames_count  = gradual_frames_count;
 
@@ -3477,6 +3487,7 @@ static inline void red_stream_maintenance(RedWorker 
*worker, Drawable *candidate
 } else {
 if (red_is_next_stream_frame(worker, candidate, prev) != 
STREAM_FRAME_NONE) {
 red_stream_add_frame(worker, candidate,
+ prev-first_frame_time,
  prev-frames_count,
  prev-gradual_frames_count,
  prev-last_gradual_frame);
@@ -3638,6 +3649,7 @@ static inline void red_use_stream_trace(RedWorker 
*worker, Drawable *drawable)
trace-dest_area, trace-time, NULL, 
FALSE) !=
STREAM_FRAME_NONE) {
 if (red_stream_add_frame(worker, drawable,
+ trace-first_frame_time

Re: [Spice-devel] [PATCH spice 6/11] server: Add VP8 support, a video codec preference list and compatibility checks with the Spice client.

2015-05-26 Thread Francois Gouget
On Tue, 19 May 2015, Marc-André Lureau wrote:
[...]
  +/* Set the encoder initial bit rate, and ask for a low latency */
  +adjust_bit_rate(encoder);
  +g_object_set(G_OBJECT(encoder-gstenc), bitrate, encoder-bit_rate, 
  NULL);
  +g_object_set(G_OBJECT(encoder-gstenc), max-latency, 0, NULL);
  +g_object_set(G_OBJECT(encoder-gstenc), max-keyframe-distance, 0, 
  NULL);
  +g_object_set(G_OBJECT(encoder-gstenc), lag-in-frames, 0, NULL);
  +
 
 Those paremeters do not exist with all encoders, notably ffenc_mjpeg.

I'll tweak it so we only set the properties supported by the current 
encoder.


 We could rather use or define encodebin profiles.

See discussion in the previous email.


[...]
  +if (encoder-base.codec_type == SPICE_VIDEO_CODEC_TYPE_VP8) {
  +/* vp8enc gets confused if we try to reconfigure the pipeline */
   reset_pipeline(encoder);
 
 You'll easily reach this condition with CAP_SIZED_STREAM streams.

It's ok. reset_pipeline() frees the current pipeline, causing 
gst_encoder_encode_frame() to call construct_pipeline() as if this was 
the stream's first frame.


[...]
   /* The GStreamer buffer timestamps and framerate are irrelevant and 
  would
* be hard to set right because they can arrive a bit irregularly
*/
  -GST_BUFFER_TIMESTAMP(buffer) = GST_CLOCK_TIME_NONE;
  -GST_BUFFER_DURATION(buffer) = GST_CLOCK_TIME_NONE;
  +if (encoder-base.codec_type == SPICE_VIDEO_CODEC_TYPE_VP8)
  +{
  +/* FIXME: Maybe try drop-frame = 0 instead? */
  +GST_BUFFER_TIMESTAMP(buffer) = frame_time;
  +GST_BUFFER_DURATION(buffer) = 1;
  +}
  +else
  +{
  +GST_BUFFER_TIMESTAMP(buffer) = GST_CLOCK_TIME_NONE;
  +GST_BUFFER_DURATION(buffer) = GST_CLOCK_TIME_NONE;
  +}
 
 What is this supposed to change? Did you consider appsrc do-timestamp
 instead?

It's a hack to get both the mjpeg end vp8 encoders working.

Using 'appsrc do-timestamp=1' works for the mjpeg encoder but causes us 
to block indefinitely in gst_app_sink_pull_buffer() for the vp8 encoder 
(independently of is-live), for an unknown reason.

My suspicion is that the frame gets dropped, presumably by vp8enc 
itself, maybe due to pipeline latency issues.

I'm also not sure yet of what the best approach is for timestamping and 
setting the framerate in the appsrc caps and their impact on the 
bitrate.

One option is to advertise the outgoing framerate, the target bitrate 
and use do-timestamping. The outgoing framerate, e.g. 10fps, may be 
lower than the source framerate, e.g. 24 fps, which implies dropping 
frames before passing them off to the pipeline. This means some frames 
will be less than 1/10th second apart and, if I remember correctly, 
this causes the pipeline to drop them which is not what we want (and 
again causes a freeze in gst_app_sink_pull_buffer()).

Another option is to set the bitrate and framerate to get the desired 
compressed buffer size. Then the stream's bitrate can be further reduced 
by controlling the outgoing frame rate. In this case I'm not sure using 
real timestamps makes sense.


  @@ -364,13 +382,13 @@ static int gst_encoder_encode_frame(GstEncoder
  *encoder,
   encoder-spice_format = bitmap-format;
   encoder-width = width;
   encoder-height = height;
  -if (encoder-pipeline  !reconfigure_pipeline(encoder))
  -return VIDEO_ENCODER_FRAME_UNSUPPORTED;
  +if (encoder-pipeline)
  +reconfigure_pipeline(encoder);
 
 Why this change?

reconfigure_pipeline() used to return false if it failed to reconfigure 
the pipeline. With the old code this would cause us to return 
FRAME_UNSUPPORTED. But in fact in such a case the existing pipeline has 
been freed and all we need to do is to rebuild it from scratch which is 
what we already do a few lines down.

This should maybe have been part of patch 5 though 
reconfigure_pipeline() does not fail with ffenc_mjpeg.


  +agent-video_encoder = red_display_create_video_encoder(dcc, 
  initial_bit_rate, video_cbs, agent);
   } else {
  -agent-video_encoder = create_video_encoder(0, NULL, NULL);
  +agent-video_encoder = red_display_create_video_encoder(dcc, 0, 
  NULL, NULL);
   }
  +/* FIXME: We may have failed to create a video encoder which will cause
  + *a crash!
  + */
 
 You may disable video streaming in this case? (worker-streaming_video ==
 STREAM_VIDEO_OFF)

The administrator could certainly set this option.

But as for gracefully handling this failure without configuration, as 
far as I can tell, by the time red_display_create_stream() fails it's 
too late to set streaming_video.


-- 
Francois Gouget fgou...@codeweavers.com___
Spice-devel mailing list
Spice-devel@lists.freedesktop.org
http://lists.freedesktop.org/mailman/listinfo/spice-devel


Re: [Spice-devel] [PATCH spice 3/11] server: Refactor the Spice server video encoding so alternative implementations can be added.

2015-05-26 Thread Francois Gouget
On Tue, 19 May 2015, Marc-André Lureau wrote:
[...]
  +struct VideoEncoder {
  +/* Releases the video encoder's resources */
  +void (*destroy)(VIDEO_ENCODER_T *encoder);
  +
  +/* Compresses the specified src image area into the outbuf buffer.
  + *
  + * @encoder:   The video encoder.
  + * @bitmap:The Spice screen.
  + * @width: The width of the Spice screen.
  + * @height:The heigth of the Spice screen.
 
 
 It's not the screen, it's the video area. It's not clear to me what 
 would happen if the src size doesn't match the widthheight.

Ah right. I'll fix the comment. I was confused about that but after 
looking again I must say I'm still unsure as to why we get both src and 
width+height.

My understanding is that this has been introduced to deal with the 
YouTube progress bar:
https://bugzilla.redhat.com/show_bug.cgi?id=813826

To sum up, the size of the video area detected by the Spice server 
changes when the progress bar pops up or down. As a result some of the 
'video frames' it gets don't match the size it detected when it created 
the video stream.

 * It used to be that this caused such frames to go through the regular 
   update mechanism instead of through the video stream. This is still 
   the case with the spicec client for instance and results in the video 
   seeming to jump back and forth because the video stream is delayed 
   due to buffering while the regular path is not.

   Looking at the impact on src  height, either the size of the video 
   frame, aka src, matches the stream size and then so do width and 
   height (lines 9  10 below), or it does not and then we don't go 
   through the video encoder (line 6 below).


 * Now clients can advertise support for changing stream sizes with the 
   SIZED_STREAM capability. This does not totally fix the back and forth 
   issue but restricts it to the progress bar area as it comes in and 
   out of the video frame.

   In that case width  height are either computed from the actual video 
   frame size, aka src, (lines 3  4 below), or default to the initial 
   stream size when the video frame size matches (lines 9  10 below).

From red_marshall_stream_data():
 1 if (drawable-sized_stream) {
 2   if (red_channel_client_test_remote_cap(rcc, 
SPICE_DISPLAY_CAP_SIZED_STREAM)) {
 3 width = src_rect-right - src_rect-left;
 4 height = src_rect-bottom - src_rect-top;
 5   } else {
 6 return FALSE;
 7   }
 8 } else {
 9   width = stream-width;
10   height = stream-height;
11 }

So in the end width and height *always* match src. So they're redundant, 
unless some larger purpose is planned for them.

Now must say having a continuously changing stream size is quite 
annoying in the context of GStreamer:
 - At a minimum it forces a reconfiguration of the pipeline which, 
   depending on the encoder, may require rebuilding it. Either cases 
   seem to cause a reset of the GStreamer's encoder bitrate control 
   algorithm which tends to cause it to overshoot and may cause frame 
   drops.
 - Ultimately the GStreamer video encoder should support inter-frame 
   compression (with VP8 or H264 for instance) and a changing stream 
   size will also cause some disruption in this context.

Things can still work as is so there's not hurry but maybe a better 
solution can be devised in time.


For instance it may be better to increase the stream size as the video 
frame size increases but then peg it so it does not shrink again. This 
would solve the remaining back and forth issue with the YouTube progress 
bar, and limit the number of resizes the video encoders have to go 
through. It supposes that regular frame updates know to ignore changes 
happening inside the stream area even if they don't go through the 
regular 'video frame' update path but I have no idea if that's easy to 
do.

Alternatively one could split oversize video frames in two: the stream 
area which would go through the video encoder, and the remainder which 
would go through the regular path. This would also solve the remaining 
back and forth issue with the YouTube progress bar and would even be 
compatible with non SIZED_STREAM capable clients.

-- 
Francois Gouget fgou...@codeweavers.com
___
Spice-devel mailing list
Spice-devel@lists.freedesktop.org
http://lists.freedesktop.org/mailman/listinfo/spice-devel


Re: [Spice-devel] [PATCH spice 4/11] server: Add a GStreamer 0.10 MJPEG video encoder and use it by default.

2015-05-26 Thread Francois Gouget
On Tue, 19 May 2015, Marc-André Lureau wrote:
[...]
 I think this should target at least gstreamer 1.0. Do you have good reasons
 to want 0.10 support?

I need to target CentOS 6.5 which does not have GStreamer 1.0. I have 
started work on adding GStreamer 1.0 support anyway but that's not 
working yet.


  +encoder-pipeline = gst_parse_launch_full(appsrc name=src is-live=1
  ! ffmpegcolorspace ! ffenc_mjpeg name=encoder ! appsink name=sink, NULL,
  GST_PARSE_FLAG_FATAL_ERRORS, err);
 
 
 Any reason to pick ffmpegcolorspace instead of autoconvert ?

Using autovideoconvert works, I'll use that instead.


 I would rather see an encodebin with a mjpeg profile or caps. However, I am
 not sure it will be possible to adjust bitrate easily. That could be done
 later.

There's also another issue which is that VP8 encoder does inter-frame 
compression. Currently that does not mesh well with neither Spice's 
video_encoder_encode_frame() API which expects to get one compressed 
buffer for each input frame, nor the current gstreamer_encoder 
implementation.

So to get VP8 support we configure the encoder to force it to only issue 
keyframes. But I'm not sure that would be possible through encodebin 
profiles, particularly in an encoder-independent way (even if just 
across VP8 encoder implementations).


  +/* We could create a bunch of GstMemory objects, one per line, to avoid
  + * copying the raw frame. But this may run into alignment problems and 
  it's
  + * unclear that it would be any faster, particularly if we're unable to
  + * cache these objects.
  + */

 It would probably help when encoding fullscreen.

Maybe. It's a GStreamer 1.0 feature so I have not had a deep look into 
it.


[...]
 Although it is much less important than the memcpy on the src, I could
 imagine the memcpy could be removed eventually, perhaps a FIXME is worth
 here.

It probably requires setting up our own buffer allocator so when the 
encoder asks for a buffer we can give it the Spice output buffer. 
That may be making too many assumptions about the encoder though, 
particularly in GStreamer 1.0. I'll add a FIXME though.


-- 
Francois Gouget fgou...@codeweavers.com___
Spice-devel mailing list
Spice-devel@lists.freedesktop.org
http://lists.freedesktop.org/mailman/listinfo/spice-devel


Re: [Spice-devel] [PATCH spice 02/13] server: Add a GStreamer 0.10 MJPEG video encoder and use it by default. (take 4)

2015-08-05 Thread Francois Gouget
The GStreamer video encoder supports both regular and sized streams.
It is otherwise quite basic and lacks any rate control: the bitrate is 
set at startup and will
not react to changes in the network conditions. Still it should work 
fine on LANs.

Signed-off-by: Francois Gouget fgou...@codeweavers.com
---


On Fri, 31 Jul 2015, Victor Toso wrote:
[...]
  +static gboolean set_appsrc_caps(GstEncoder *encoder)
  +{
  +GstCaps *new_caps = gst_caps_new_simple(video/x-raw-rgb,
  +bpp, G_TYPE_INT, encoder-format-bpp,
  +depth, G_TYPE_INT, encoder-format-depth,
  +width, G_TYPE_INT, encoder-width,
  +height, G_TYPE_INT, encoder-height,
  +endianness, G_TYPE_INT, encoder-format-endianness,
  +red_mask, G_TYPE_INT, encoder-format-red_mask,
  +green_mask, G_TYPE_INT, encoder-format-green_mask,
  +blue_mask, G_TYPE_INT, encoder-format-blue_mask,
  +framerate, GST_TYPE_FRACTION, get_source_fps(encoder), 1,
  +NULL);
  +if (!new_caps) {
  +spice_warning(GStreamer error: could not create the source caps);
  +reset_pipeline(encoder);
  +return FALSE;
 
 This function is called twice and one of them do reset_pipeline in case
 of failure. I would remove reset_pipeline here to be dealt by who called
 it.
 
 (I'm not sure if it is possible to gst_caps_new_simple return NULL)

I looked at the GStreamer code and gst_caps_new_simple() is not supposed 
to fail. So I tweaked set_appsrc_caps() accordingly.


  +/* A helper for gst_encoder_encode_frame(). */
  +static gboolean construct_pipeline(GstEncoder *encoder, const SpiceBitmap 
  *bitmap)
  +{
  +GError *err = NULL;
  +const gchar* desc = appsrc name=src format=2 do-timestamp=true ! 
  ffmpegcolorspace ! ffenc_mjpeg name=encoder ! appsink name=sink;
 
 Either keep * with the type or with variable.

Eh. I tend to prefer keeping it with the type but that's not the Spice 
style. I slipped. That's fixed.


  +spice_debug(GStreamer pipeline: %s, desc);
  +encoder-pipeline = gst_parse_launch_full(desc, NULL, 
  GST_PARSE_FLAG_FATAL_ERRORS, err);
  +if (!encoder-pipeline) {
 
 I guess we want to check the err != NULL as well as
 gst_parse_launch_full may return non NULL pipeline even if error is set.
 /me believes that if the pipeline had an error to be created we should
 not try to play it.

Makes sense. Done.


  +/* Start playing */
  +spice_debug(removing the pipeline clock);
  +gst_pipeline_use_clock(GST_PIPELINE(encoder-pipeline), NULL);
 
 This is related to ffenc_mjpeg described in the mail, right?
 I think it would be good to open a bug against 0.10 version and add a
 FIXME here to track the issue.
 
 https://bugzilla.gnome.org/enter_bug.cgi?product=GStreamer

I have reported the issue in bug 753257 which is probably identical to 
bug 724103:
https://bugzilla.gnome.org/show_bug.cgi?id=753257 
https://bugzilla.gnome.org/show_bug.cgi?id=724103

I also added a reference to the bug in the source. Clearly this will not 
be fixed for GStreamer 0.10 but maybe there's still hope for GStreamer 
1.0.


  +/* A helper for gst_encoder_encode_frame(). */
  +static int push_raw_frame(GstEncoder *encoder, const SpiceBitmap *bitmap,
  +  const SpiceRect *src, int top_down)
  +{
[...]
 
 I think we definitely need more help functions here to set the GstBuffer.
 Later patches introduce gst 1.0 and the zero-copy and this becomes a bit
 hard to track.

The different part are quite strongly coupled. I still managed to split 
off the line-by-line copy and zero copy code. Hopefully it makes things 
clearer.


  +/* A helper for gst_encoder_encode_frame(). */
  +static int pull_compressed_buffer(GstEncoder *encoder,
  +  uint8_t **outbuf, size_t *outbuf_size,
  +  int *data_size)
  +{
 
 This will be totally changed when video encoder manage the compressed
 buffer.

Yes. Letting the video encoder manage the compressed buffer is a 
relatively big change so I prefer to send it separately.


  +spice_debug(video format change: width %d - %d, height %d - %d, 
  format %d - %d, encoder-width, width, encoder-height, height, 
  encoder-spice_format, bitmap-format);
 
 Please, break this 180 chars line.

Done.


  +if (!encoder-pipeline  !construct_pipeline(encoder, bitmap)) {
  +return VIDEO_ENCODER_FRAME_UNSUPPORTED;
 
 If we reach this we may need a spice_warning, no?

Actually the warning is issued by construct_pipeline(), which is where 
we know most about what went wrong. So I don't think we need an 
additional warning there.


  +static void gst_encoder_notify_server_frame_drop(GstEncoder *encoder)
  +{
  +spice_debug(server report: getting frame drops...);
 
 This will be improved in following patches

Yes. This is mostly a placeholder at this stage.



diff --git a/configure.ac b/configure.ac
index 5b4caa4..ca91b5a 100644
--- a/configure.ac

[Spice-devel] [PATCH v2 7/7] spice-gtk: Use typefind and decodebin as fallbacks to set up the GStreamer pipeline.

2015-08-06 Thread Francois Gouget
Potentially this means future video codecs can be supported automatically.
One can also force usage of typefind and decodebin by setting the 
SPICE_GST_AUTO environment variable. If set to 'decodebin' then only decodebin 
will be used.

Signed-off-by: Francois Gouget fgou...@codeweavers.com
---
 src/channel-display-gst.c | 22 +++---
 1 file changed, 15 insertions(+), 7 deletions(-)

diff --git a/src/channel-display-gst.c b/src/channel-display-gst.c
index 59ce3e1..3d9274b 100644
--- a/src/channel-display-gst.c
+++ b/src/channel-display-gst.c
@@ -110,27 +110,35 @@ static gboolean construct_pipeline(GstDecoder *decoder)
 decoder-pipeline_wait = 1;
 decoder-samples_count = 0;
 
-const gchar *src_caps, *gstdec_name;
+const gchar *src_caps = NULL;
+const gchar *gstdec_name = NULL;
 switch (decoder-base.codec_type) {
 case SPICE_VIDEO_CODEC_TYPE_MJPEG:
-src_caps = image/jpeg;
+src_caps = caps=image/jpeg;
 gstdec_name = jpegdec;
 break;
 case SPICE_VIDEO_CODEC_TYPE_VP8:
-src_caps = video/x-vp8;
+src_caps = caps=video/x-vp8;
 gstdec_name = vp8dec;
 break;
 case SPICE_VIDEO_CODEC_TYPE_H264:
-src_caps = video/x-h264;
+src_caps = caps=video/x-h264;
 gstdec_name = h264parse ! avdec_h264;
 break;
 default:
-spice_warning(Unknown codec type %d, decoder-base.codec_type);
-return -1;
+SPICE_DEBUG(Unknown codec type %d, decoder-base.codec_type);
+break;
+}
+const gchar *gst_auto = getenv(SPICE_GST_AUTO);
+if (!src_caps || (gst_auto  strcmp(gst_auto, decodebin))) {
+src_caps = typefind=true; /* Misidentifies VP8 */
+}
+if (!gstdec_name || gst_auto) {
+gstdec_name = decodebin;  /* vaapi is assert-happy */
 }
 
 GError *err = NULL;
-gchar *desc = g_strdup_printf(appsrc name=src format=2 do-timestamp=1 
caps=%s ! %s ! videoconvert ! appsink name=sink caps=video/x-raw,format=BGRx, 
src_caps, gstdec_name);
+gchar *desc = g_strdup_printf(appsrc name=src format=2 do-timestamp=1 %s 
! %s ! videoconvert ! appsink name=sink caps=video/x-raw,format=BGRx, 
src_caps, gstdec_name);
 SPICE_DEBUG(GStreamer pipeline: %s, desc);
 decoder-pipeline = gst_parse_launch_full(desc, NULL, 
GST_PARSE_FLAG_FATAL_ERRORS, err);
 g_free(desc);
-- 
2.4.6
___
Spice-devel mailing list
Spice-devel@lists.freedesktop.org
http://lists.freedesktop.org/mailman/listinfo/spice-devel


[Spice-devel] [PATCH v2 6/7] spice-gtk: Make it possible to disable support for the builtin MJPEG video decoder.

2015-08-06 Thread Francois Gouget
This makes it possible to test the GStreamer video decoder with MJPEG streams.

Signed-off-by: Francois Gouget fgou...@codeweavers.com
---
 configure.ac  | 8 
 src/Makefile.am   | 7 ++-
 src/channel-display.c | 2 ++
 3 files changed, 16 insertions(+), 1 deletion(-)

diff --git a/configure.ac b/configure.ac
index 003e351..1b1df3e 100644
--- a/configure.ac
+++ b/configure.ac
@@ -355,6 +355,14 @@ AM_CONDITIONAL([HAVE_GSTVIDEO], [test x$have_gst_video = 
xyes])]
 AC_SUBST(GSTVIDEO_CFLAGS)
 AC_SUBST(GSTVIDEO_LIBS)
 
+AC_ARG_ENABLE([builtin-mjpeg],
+  AS_HELP_STRING([--enable-builtin-mjpeg], [Enable the builtin mjpeg video 
decoder @:@default=yes@:@]),
+  [],
+  enable_builtin_mjpeg=yes)
+AS_IF([test x$enable_builtin_mjpeg = xyes],
+  [AC_DEFINE([WITH_BUILTIN_MJPEG], 1, [Use the builtin mjpeg decoder?])])
+AM_CONDITIONAL(WITH_BUILTIN_MJPEG, [test x$enable_builtin_mjpeg != xno])
+
 AC_CHECK_LIB(jpeg, jpeg_destroy_decompress,
 AC_MSG_CHECKING([for jpeglib.h])
 AC_TRY_CPP(
diff --git a/src/Makefile.am b/src/Makefile.am
index 925c75f..e744ce9 100644
--- a/src/Makefile.am
+++ b/src/Makefile.am
@@ -255,7 +255,6 @@ libspice_client_glib_2_0_la_SOURCES =   
\
channel-cursor.c\
channel-display.c   \
channel-display-priv.h  \
-   channel-display-mjpeg.c \
channel-inputs.c\
channel-main.c  \
channel-playback.c  \
@@ -342,6 +341,12 @@ libspice_client_glib_2_0_la_SOURCES += \
$(NULL)
 endif
 
+if WITH_BUILTIN_MJPEG
+libspice_client_glib_2_0_la_SOURCES += \
+   channel-display-mjpeg.c \
+   $(NULL)
+endif
+
 if HAVE_GSTVIDEO
 libspice_client_glib_2_0_la_SOURCES += \
channel-display-gst.c   \
diff --git a/src/channel-display.c b/src/channel-display.c
index 7756d35..cb717d3 100644
--- a/src/channel-display.c
+++ b/src/channel-display.c
@@ -1009,9 +1009,11 @@ static void display_handle_stream_create(SpiceChannel 
*channel, SpiceMsgIn *in)
 display_update_stream_region(st);
 
 switch (op-codec_type) {
+#ifdef WITH_BUILTIN_MJPEG
 case SPICE_VIDEO_CODEC_TYPE_MJPEG:
 st-video_decoder = create_mjpeg_decoder(op-codec_type, st);
 break;
+#endif
 default:
 st-video_decoder = create_gstreamer_decoder(op-codec_type, st);
 }
-- 
2.4.6

___
Spice-devel mailing list
Spice-devel@lists.freedesktop.org
http://lists.freedesktop.org/mailman/listinfo/spice-devel


[Spice-devel] [PATCH v2 4/7] spice-gtk: Add a GStreamer video decoder with support for MJPEG, VP8 and h264.

2015-08-06 Thread Francois Gouget
Based on a patch by Jeremy White.
Signed-off-by: Francois Gouget fgou...@codeweavers.com
---

Note that this patch depends on the spice-common patch so a spice-common 
commit is in order, either separately or as part of this commit.

 configure.ac   |  47 +++---
 src/Makefile.am|  12 ++-
 src/channel-display-gst.c  | 216 +
 src/channel-display-priv.h |   1 +
 src/channel-display.c  |   6 +-
 5 files changed, 265 insertions(+), 17 deletions(-)
 create mode 100644 src/channel-display-gst.c

diff --git a/configure.ac b/configure.ac
index 1b347c0..003e351 100644
--- a/configure.ac
+++ b/configure.ac
@@ -299,7 +299,7 @@ AC_ARG_WITH([audio],
 
 case $with_audio in
   gstreamer|pulse|auto*)
-PKG_CHECK_MODULES(GST, gstreamer-1.0 gstreamer-base-1.0 gstreamer-app-1.0 
gstreamer-audio-1.0, [have_gst=yes], [have_gst=no])
+PKG_CHECK_MODULES(GSTAUDIO, gstreamer-1.0 gstreamer-base-1.0 
gstreamer-app-1.0 gstreamer-audio-1.0, [have_gst_audio=yes], 
[have_gst_audio=no])
 PKG_CHECK_MODULES(PULSE, libpulse libpulse-mainloop-glib, 
[have_pulse=yes], [have_pulse=no])
 ;;
   no*)
@@ -310,7 +310,7 @@ esac
 AS_IF([test x$with_audio = xauto  test x$have_pulse = xyes],
   [with_audio=pulse])
 
-AS_IF([test x$with_audio = xauto  test x$have_gst = xyes],
+AS_IF([test x$with_audio = xauto  test x$have_gst_audio = xyes],
   [with_audio=gstreamer])
 
 AS_IF([test x$with_audio = xauto],
@@ -319,22 +319,41 @@ AS_IF([test x$with_audio = xauto],
 AS_IF([test x$with_audio = xpulse],
   [AS_IF([test x$have_pulse = xyes],
  [AC_DEFINE([WITH_PULSE], 1, [Have pulseaudio?])],
- [AC_MSG_ERROR([PulseAudio requested but not found])
-  ])
-])
+ [AC_MSG_ERROR([PulseAudio requested but not found])]
+  )]
+)
 AM_CONDITIONAL([WITH_PULSE], [test x$have_pulse = xyes])
 AC_SUBST(PULSE_CFLAGS)
 AC_SUBST(PULSE_LIBS)
 
 AS_IF([test x$with_audio = xgstreamer],
-  [AS_IF([test x$have_gst = xyes],
- [AC_DEFINE([WITH_GSTAUDIO], 1, [Have GStreamer 1.0?])],
- [AC_MSG_ERROR([GStreamer 1.0 requested but not found])
-  ])
-])
-AM_CONDITIONAL([WITH_GSTAUDIO], [test x$have_gst = xyes])
-AC_SUBST(GST_CFLAGS)
-AC_SUBST(GST_LIBS)
+  [AS_IF([test x$have_gst_audio = xyes],
+ [AC_DEFINE([WITH_GSTAUDIO], 1, [Have GStreamer 1.0 audio?])],
+ [AC_MSG_ERROR([GStreamer 1.0 audio requested but not found])]
+  )]
+)
+AM_CONDITIONAL([WITH_GSTAUDIO], [test x$have_gst_audio = xyes])
+AC_SUBST(GSTAUDIO_CFLAGS)
+AC_SUBST(GSTAUDIO_LIBS)
+
+AC_ARG_ENABLE([gst-video],
+  AS_HELP_STRING([--enable-gst-video=@:@auto/yes/no@:@],
+ [Enable GStreamer video support 
@:@default=auto@:@]),
+  [],
+  [enable_gst_video=auto])
+
+AS_IF([test x$enable_gst_video != xno],
+  [PKG_CHECK_MODULES(GSTVIDEO, gstreamer-1.0 gstreamer-base-1.0 
gstreamer-app-1.0 gstreamer-video-1.0, [have_gst_video=yes], 
[have_gst_video=no])
+   AS_IF([test x$have_gst_video = xyes],
+ [AC_DEFINE([HAVE_GSTVIDEO], 1, [Have GStreamer 1.0 video?])],
+ [AS_IF([test x$enable_gst_video = xyes],
+[AC_MSG_ERROR([GStreamer 1.0 video requested but not 
found])]
+  )]
+   )]
+)
+AM_CONDITIONAL([HAVE_GSTVIDEO], [test x$have_gst_video = xyes])]
+AC_SUBST(GSTVIDEO_CFLAGS)
+AC_SUBST(GSTVIDEO_LIBS)
 
 AC_CHECK_LIB(jpeg, jpeg_destroy_decompress,
 AC_MSG_CHECKING([for jpeglib.h])
@@ -700,7 +719,7 @@ SPICE_CFLAGS=$SPICE_CFLAGS $WARN_CFLAGS
 
 AC_SUBST(SPICE_CFLAGS)
 
-SPICE_GLIB_CFLAGS=$PROTOCOL_CFLAGS $PIXMAN_CFLAGS $PULSE_CFLAGS $GST_CFLAGS 
$GLIB2_CFLAGS $GIO_CFLAGS $GOBJECT2_CFLAGS $SSL_CFLAGS $SASL_CFLAGS
+SPICE_GLIB_CFLAGS=$PROTOCOL_CFLAGS $PIXMAN_CFLAGS $PULSE_CFLAGS 
$GSTVIDEO_CFLAGS $GSTAUDIO_CFLAGS $GLIB2_CFLAGS $GIO_CFLAGS $GOBJECT2_CFLAGS 
$SSL_CFLAGS $SASL_CFLAGS
 SPICE_GTK_CFLAGS=$SPICE_GLIB_CFLAGS $GTK_CFLAGS 
 
 AC_SUBST(SPICE_GLIB_CFLAGS)
diff --git a/src/Makefile.am b/src/Makefile.am
index cf02198..925c75f 100644
--- a/src/Makefile.am
+++ b/src/Makefile.am
@@ -96,7 +96,8 @@ SPICE_COMMON_CPPFLAGS =   
\
$(GOBJECT2_CFLAGS)  \
$(SSL_CFLAGS)   \
$(SASL_CFLAGS)  \
-   $(GST_CFLAGS)   \
+   $(GSTAUDIO_CFLAGS)  \
+   $(GSTVIDEO_CFLAGS)  \
$(SMARTCARD_CFLAGS) \
$(USBREDIR_CFLAGS)  \
$(GUDEV_CFLAGS) \
@@ -207,7 +208,8 @@ libspice_client_glib_2_0_la_LIBADD =
\
$(PIXMAN_LIBS

[Spice-devel] [PATCH v2 5/7] spice-gtk: Avoid copying the compressed message data in the GStreamer decoder.

2015-08-06 Thread Francois Gouget
Signed-off-by: Francois Gouget fgou...@codeweavers.com
---
 src/channel-display-gst.c | 89 ---
 1 file changed, 84 insertions(+), 5 deletions(-)

diff --git a/src/channel-display-gst.c b/src/channel-display-gst.c
index 3024356..59ce3e1 100644
--- a/src/channel-display-gst.c
+++ b/src/channel-display-gst.c
@@ -48,11 +48,43 @@ struct GstDecoder {
 
 /* -- Output frame data -- */
 
+GMutex pipeline_mutex;
+GCond pipeline_cond;
+int pipeline_wait;
+uint32_t samples_count;
+
 GstSample *sample;
 GstMapInfo mapinfo;
 };
 
 
+/* Signals that the pipeline is done processing the last buffer we gave it.
+ *
+ * @decoder:   The video decoder object.
+ * @samples:   How many samples to add to the available samples count.
+ */
+static void signal_pipeline(GstDecoder *decoder, uint32_t samples)
+{
+g_mutex_lock(decoder-pipeline_mutex);
+decoder-pipeline_wait = 0;
+decoder-samples_count += samples;
+g_cond_signal(decoder-pipeline_cond);
+g_mutex_unlock(decoder-pipeline_mutex);
+}
+
+static void appsrc_need_data_cb(GstAppSrc *src, guint length, gpointer 
user_data)
+{
+GstDecoder *decoder = (GstDecoder*)user_data;
+signal_pipeline(decoder, 0);
+}
+
+static GstFlowReturn appsink_new_sample_cb(GstAppSink *appsrc, gpointer 
user_data)
+{
+GstDecoder *decoder = (GstDecoder*)user_data;
+signal_pipeline(decoder, 1);
+return GST_FLOW_OK;
+}
+
 /* -- GStreamer pipeline -- */
 
 static void reset_pipeline(GstDecoder *decoder)
@@ -66,10 +98,18 @@ static void reset_pipeline(GstDecoder *decoder)
 gst_object_unref(decoder-appsink);
 gst_object_unref(decoder-pipeline);
 decoder-pipeline = NULL;
+
+g_mutex_clear(decoder-pipeline_mutex);
+g_cond_clear(decoder-pipeline_cond);
 }
 
 static gboolean construct_pipeline(GstDecoder *decoder)
 {
+g_mutex_init(decoder-pipeline_mutex);
+g_cond_init(decoder-pipeline_cond);
+decoder-pipeline_wait = 1;
+decoder-samples_count = 0;
+
 const gchar *src_caps, *gstdec_name;
 switch (decoder-base.codec_type) {
 case SPICE_VIDEO_CODEC_TYPE_MJPEG:
@@ -101,7 +141,12 @@ static gboolean construct_pipeline(GstDecoder *decoder)
 }
 
 decoder-appsrc = 
GST_APP_SRC(gst_bin_get_by_name(GST_BIN(decoder-pipeline), src));
+GstAppSrcCallbacks appsrc_cbs = {appsrc_need_data_cb, NULL, NULL};
+gst_app_src_set_callbacks(decoder-appsrc, appsrc_cbs, decoder, NULL);
+
 decoder-appsink = 
GST_APP_SINK(gst_bin_get_by_name(GST_BIN(decoder-pipeline), sink));
+GstAppSinkCallbacks appsink_cbs = {NULL, NULL, appsink_new_sample_cb};
+gst_app_sink_set_callbacks(decoder-appsink, appsink_cbs, decoder, NULL);
 
 if (gst_element_set_state(decoder-pipeline, GST_STATE_PLAYING) == 
GST_STATE_CHANGE_FAILURE) {
 SPICE_DEBUG(GStreamer error: Unable to set the pipeline to the 
playing state.);
@@ -112,6 +157,11 @@ static gboolean construct_pipeline(GstDecoder *decoder)
 return TRUE;
 }
 
+static void release_msg_in(gpointer data)
+{
+spice_msg_in_unref((SpiceMsgIn*)data);
+}
+
 static gboolean push_compressed_buffer(GstDecoder *decoder,
SpiceMsgIn *frame_msg)
 {
@@ -122,10 +172,11 @@ static gboolean push_compressed_buffer(GstDecoder 
*decoder,
 return FALSE;
 }
 
-// TODO.  Grr.  Seems like a wasted alloc
-gpointer d = g_malloc(size);
-memcpy(d, data, size);
-GstBuffer *buffer = gst_buffer_new_wrapped(d, size);
+/* Reference frame_msg so it stays around until our 'deallocator' releases 
it */
+spice_msg_in_ref(frame_msg);
+GstBuffer *buffer = gst_buffer_new_wrapped_full(GST_MEMORY_FLAG_READONLY,
+data, size, 0, size,
+frame_msg, 
release_msg_in);
 
 if (gst_app_src_push_buffer(decoder-appsrc, buffer) != GST_FLOW_OK) {
 SPICE_DEBUG(GStreamer error: unable to push frame of size %d, size);
@@ -195,8 +246,36 @@ static uint8_t* gst_decoder_decode_frame(GstDecoder 
*decoder,
  */
 release_last_frame(decoder);
 
+/* The pipeline may have called appsrc_need_data_cb() after we got the last
+ * output frame. This would cause us to return prematurely so reset
+ * pipeline_wait so we do wait for it to process this buffer.
+ */
+g_mutex_lock(decoder-pipeline_mutex);
+decoder-pipeline_wait = 1;
+g_mutex_unlock(decoder-pipeline_mutex);
+/* Note that it's possible for appsrc_need_data_cb() to get called between
+ * now and the pipeline wait. But this will at most cause a one frame 
delay.
+ */
+
 if (push_compressed_buffer(decoder, frame_msg)) {
-return pull_raw_frame(decoder);
+/* Wait for the pipeline to either produce a decoded frame, or ask
+ * for more data which means an error happened.
+ */
+g_mutex_lock(decoder-pipeline_mutex

[Spice-devel] [PATCH v2 3/7] spice-common: Add support for the VP8 and h264 video codecs.

2015-08-06 Thread Francois Gouget
Signed-off-by: Francois Gouget fgou...@codeweavers.com
---

This is identical to this patch:
http://lists.freedesktop.org/archives/spice-devel/2015-July/020984.html

 spice.proto | 2 ++
 1 file changed, 2 insertions(+)

diff --git a/spice.proto b/spice.proto
index 4ea1263..fa4d448 100644
--- a/spice.proto
+++ b/spice.proto
@@ -329,6 +329,8 @@ flags8 path_flags { /* TODO: C enum names changes */
 
 enum8 video_codec_type {
 MJPEG = 1,
+VP8,
+H264,
 };
 
 flags8 stream_flags {
-- 
2.1.4

___
Spice-devel mailing list
Spice-devel@lists.freedesktop.org
http://lists.freedesktop.org/mailman/listinfo/spice-devel


[Spice-devel] [PATCH v2 2/7] spice-proto: Add support for the VP8 and H264 video codecs and for advertising supported video codecs.

2015-08-06 Thread Francois Gouget
Clients that support multiple codecs should advertise the 
SPICE_DISPLAY_CAP_MULTI_CODEC capability and one SPICE_DISPLAY_CAP_CODEC_XXX 
per supported codec.
Signed-off-by: Francois Gouget fgou...@codeweavers.com
---

This is identical to this patch:
http://lists.freedesktop.org/archives/spice-devel/2015-July/020986.html

This should be followed by a spice-common commit that ensures we get the 
right version of these headers (possibly that commit could be part of 
the commit of 3/7).

 spice/enums.h| 2 ++
 spice/protocol.h | 4 
 2 files changed, 6 insertions(+)

diff --git a/spice/enums.h b/spice/enums.h
index 6a0ab0b..36b0ea3 100644
--- a/spice/enums.h
+++ b/spice/enums.h
@@ -139,6 +139,8 @@ typedef enum SpicePathFlags {
 
 typedef enum SpiceVideoCodecType {
 SPICE_VIDEO_CODEC_TYPE_MJPEG = 1,
+SPICE_VIDEO_CODEC_TYPE_VP8,
+SPICE_VIDEO_CODEC_TYPE_H264,
 
 SPICE_VIDEO_CODEC_TYPE_ENUM_END
 } SpiceVideoCodecType;
diff --git a/spice/protocol.h b/spice/protocol.h
index d3c5962..614dcf1 100644
--- a/spice/protocol.h
+++ b/spice/protocol.h
@@ -135,6 +135,10 @@ enum {
 SPICE_DISPLAY_CAP_STREAM_REPORT,
 SPICE_DISPLAY_CAP_LZ4_COMPRESSION,
 SPICE_DISPLAY_CAP_PREF_COMPRESSION,
+SPICE_DISPLAY_CAP_MULTI_CODEC,
+SPICE_DISPLAY_CAP_CODEC_MJPEG,
+SPICE_DISPLAY_CAP_CODEC_VP8,
+SPICE_DISPLAY_CAP_CODEC_H264,
 };
 
 enum {
-- 
2.1.4
___
Spice-devel mailing list
Spice-devel@lists.freedesktop.org
http://lists.freedesktop.org/mailman/listinfo/spice-devel


[Spice-devel] [PATCH v2 0/7] spice-gtk: Use GStreamer to decode video

2015-08-06 Thread Francois Gouget

This follows up on the initial GStreamer patch series but focuses on 
the spice-gtk client this time around.

The spice-gtk support is totally compatible with old servers so this 
patch series can be applied independently from server-side GStreamer 
video encoding support. In fact spice-gtk uses Spice's builtin MJPEG 
support by default, so essentially nothing will change. But it's 
possible to force spice-gtk to use GStreamer for MJPEG streams at build 
time; and if support for other codecs is added to the server, then this 
client will be able to decode them.


As usual, one can also find these patches on GitHub. See the gst branch 
of the repositories below:

spice:  https://github.com/fgouget/spice
spice-gtk:  https://github.com/fgouget/spice-gtk
xf86-video-qxl: https://github.com/fgouget/xf86-video-qxl

spice-common:   https://github.com/fgouget/spice-common
spice-protocol: https://github.com/fgouget/spice-protocol

(there's also 'extras' branches with more experimental/future patches 
for the curious)

For spice-html5 and QEMU one would have to refer to the patches posted 
previously on spice-devel.

Let me know if there are changes that are needed for inclusion. 


-- 
Francois Gouget fgou...@codeweavers.com  
___
Spice-devel mailing list
Spice-devel@lists.freedesktop.org
http://lists.freedesktop.org/mailman/listinfo/spice-devel


Re: [Spice-devel] [PATCH spice 01/13] server: Refactor the Spice server video encoding so alternative implementations can be added. (take 4)

2015-08-04 Thread Francois Gouget
This patch simply replaces the mjpeg_encoder_xxx() call points with a 
more object oriented
design.

Signed-off-by: Francois Gouget fgou...@codeweavers.com
---


On Fri, 31 Jul 2015, Victor Toso wrote:
[...]
  +static inline uint8_t *get_image_line(SpiceChunks *chunks, size_t *offset,
  +  int *chunk_nr, int stride)
 
 Lining up with opening parenthesis

Done.


  +static int encode_mjpeg_frame(MJpegEncoder *encoder, const SpiceRect *src,
  +const SpiceBitmap *image, int top_down)
 
 Lining up with opening parenthesis

Done.


  +for (i = 0; i  skip_lines; i++) {
  +get_image_line(chunks, offset, chunk, image_stride);
 
 Decrease one level of identation

Done.


  +if (!src_line) {
  +return FALSE;
  +}
 
 I would remove the brances of above if to keep equal to the if bellow
 
  +
  +src_line += src-left * mjpeg_encoder_get_bytes_per_pixel(encoder);
  +if (mjpeg_encoder_encode_scanline(encoder, src_line, stream_width) 
  == 0)
  +return FALSE;
  +}

Actually I introduced the if below too and it violates the coding 
standard that says if statements should always have braces. So I've done 
a pass through all my patches and it seems this file contained the only 
3 incorrect if statements.


  @@ -2693,18 +2693,19 @@ static void red_stop_stream(RedWorker *worker, 
  Stream *stream)
   region_clear(stream_agent-vis_region);
   region_clear(stream_agent-clip);
   spice_assert(!pipe_item_is_linked(stream_agent-destroy_item));
  -if (stream_agent-mjpeg_encoder  
  dcc-use_mjpeg_encoder_rate_control) {
  -uint64_t stream_bit_rate = 
  mjpeg_encoder_get_bit_rate(stream_agent-mjpeg_encoder);
  -
  -if (stream_bit_rate  dcc-streams_max_bit_rate) {
  -spice_debug(old max-bit-rate=%.2f new=%.2f,
  -dcc-streams_max_bit_rate / 8.0 / 1024.0 / 1024.0,
  -stream_bit_rate / 8.0 / 1024.0 / 1024.0);
  -dcc-streams_max_bit_rate = stream_bit_rate;
  +if (stream_agent-video_encoder) {
  +if (dcc-use_video_encoder_rate_control) {
  +uint64_t stream_bit_rate = 
  stream_agent-video_encoder-get_bit_rate(stream_agent-video_encoder);
  +if (stream_bit_rate  dcc-streams_max_bit_rate) {
  +spice_debug(old max-bit-rate=%.2f new=%.2f,
  +dcc-streams_max_bit_rate / 8.0 / 1024.0 / 1024.0,
  +stream_bit_rate / 8.0 / 1024.0 / 1024.0);
  +dcc-streams_max_bit_rate = stream_bit_rate;
  +}
   }
  +stream-refs++;
  +red_channel_client_pipe_add(dcc-common.base, 
  stream_agent-destroy_item);
 
 Here you actually changed the logic a bit, moving the strem ref and
 red_channel_client_pipe_add into the if. It does seem correct but I was
 wondering if stream_agent-mjpeg_encoder could be NULL before...

I have not been able to determine that.

mjpeg_encoder is set in the following locations:
 * red_display_create_stream()
   This is where mjpeg_encoder is initialized and in the old code this 
   could not fail. In future patches this may fail.

 * red_display_stream_agent_stop()
 * red_display_destroy_streams_agents()
   Checks whether it is non-NULL and then resets it to NULL.

And mjpeg_encoder is checked against NULL in the following places.
 * red_print_stream_stats()
 * red_stop_stream()
 * red_display_update_streams_max_latency()

But red_marshall_stream_data() assumes it is not NULL.


So clearly mjpeg_encoder is normally not NULL in red_stop_stream() and 
red_print_stream_stats() otherwise they would be unable to collect the 
bit rate and stream statistics. But I could not rule it out 
with certainty.

Let me know if you'd prefer this chunk to go in separately.





diff --git a/server/Makefile.am b/server/Makefile.am
index 89a375c..36b6d45 100644
--- a/server/Makefile.am
+++ b/server/Makefile.am
@@ -81,7 +81,6 @@ libspice_server_la_SOURCES =  \
main_channel.c  \
main_channel.h  \
mjpeg_encoder.c \
-   mjpeg_encoder.h \
red_bitmap_utils.h  \
red_channel.c   \
red_channel.h   \
@@ -115,6 +114,7 @@ libspice_server_la_SOURCES =\
spicevmc.c  \
spice_timer_queue.c \
spice_timer_queue.h \
+   video_encoder.h \
zlib_encoder.c  \
zlib_encoder.h  \
spice_bitmap_utils.h\
diff --git a/server/mjpeg_encoder.c b/server/mjpeg_encoder.c
index 9a41ef3..48042ba

[Spice-devel] [PATCH spice 01/13] server: Refactor the Spice server video encoding so alternative implementations can be added. (take 4)

2015-07-21 Thread Francois Gouget
This patch simply replaces the mjpeg_encoder_xxx() call points with a more 
object oriented design.

Signed-off-by: Francois Gouget fgou...@codeweavers.com
---

Changes since take 3:
 - A NULL video_encoder means that the stream creation failed so 
   red_stop_stream() no longer sends messages to destroy it in
   that case. This avoids getting error messages in spice-gtk.

 - Removed some forward declarations and made more functions static.

 - Tweaked some video_encoder.h comments.

Changes since take 2:
 - No change.

Changes since take 1:
 - I fixed the width/height comments and they now state that they always 
   match src.


 server/Makefile.am |   2 +-
 server/mjpeg_encoder.c | 227 +++--
 server/mjpeg_encoder.h | 114 -
 server/red_worker.c| 173 -
 server/video_encoder.h | 165 +++
 5 files changed, 381 insertions(+), 300 deletions(-)
 delete mode 100644 server/mjpeg_encoder.h
 create mode 100644 server/video_encoder.h

diff --git a/server/Makefile.am b/server/Makefile.am
index 89a375c..36b6d45 100644
--- a/server/Makefile.am
+++ b/server/Makefile.am
@@ -81,7 +81,6 @@ libspice_server_la_SOURCES =  \
main_channel.c  \
main_channel.h  \
mjpeg_encoder.c \
-   mjpeg_encoder.h \
red_bitmap_utils.h  \
red_channel.c   \
red_channel.h   \
@@ -115,6 +114,7 @@ libspice_server_la_SOURCES =\
spicevmc.c  \
spice_timer_queue.c \
spice_timer_queue.h \
+   video_encoder.h \
zlib_encoder.c  \
zlib_encoder.h  \
spice_bitmap_utils.h\
diff --git a/server/mjpeg_encoder.c b/server/mjpeg_encoder.c
index 9a41ef3..48042ba 100644
--- a/server/mjpeg_encoder.c
+++ b/server/mjpeg_encoder.c
@@ -20,7 +20,11 @@
 #endif
 
 #include red_common.h
-#include mjpeg_encoder.h
+
+typedef struct MJpegEncoder MJpegEncoder;
+#define VIDEO_ENCODER_T MJpegEncoder
+#include video_encoder.h
+
 #include jerror.h
 #include jpeglib.h
 #include inttypes.h
@@ -154,6 +158,7 @@ typedef struct MJpegEncoderRateControl {
 } MJpegEncoderRateControl;
 
 struct MJpegEncoder {
+VideoEncoder base;
 uint8_t *row;
 uint32_t row_size;
 int first_frame;
@@ -165,7 +170,7 @@ struct MJpegEncoder {
 void (*pixel_converter)(uint8_t *src, uint8_t *dest);
 
 MJpegEncoderRateControl rate_control;
-MJpegEncoderRateControlCbs cbs;
+VideoEncoderRateControlCbs cbs;
 void *cbs_opaque;
 
 /* stats */
@@ -174,11 +179,6 @@ struct MJpegEncoder {
 uint32_t num_frames;
 };
 
-static inline void mjpeg_encoder_reset_quality(MJpegEncoder *encoder,
-   int quality_id,
-   uint32_t fps,
-   uint64_t frame_enc_size);
-static uint32_t get_max_fps(uint64_t frame_size, uint64_t bytes_per_sec);
 static void mjpeg_encoder_process_server_drops(MJpegEncoder *encoder);
 static uint32_t get_min_required_playback_delay(uint64_t frame_enc_size,
 uint64_t byte_rate,
@@ -189,49 +189,14 @@ static inline int rate_control_is_active(MJpegEncoder* 
encoder)
 return encoder-cbs.get_roundtrip_ms != NULL;
 }
 
-MJpegEncoder *mjpeg_encoder_new(uint64_t starting_bit_rate,
-MJpegEncoderRateControlCbs *cbs, void *opaque)
-{
-MJpegEncoder *enc;
-
-spice_assert(!cbs || (cbs  cbs-get_roundtrip_ms  
cbs-get_source_fps));
-
-enc = spice_new0(MJpegEncoder, 1);
-
-enc-first_frame = TRUE;
-enc-rate_control.byte_rate = starting_bit_rate / 8;
-enc-starting_bit_rate = starting_bit_rate;
-
-if (cbs) {
-struct timespec time;
-
-clock_gettime(CLOCK_MONOTONIC, time);
-enc-cbs = *cbs;
-enc-cbs_opaque = opaque;
-mjpeg_encoder_reset_quality(enc, MJPEG_QUALITY_SAMPLE_NUM / 2, 5, 0);
-enc-rate_control.during_quality_eval = TRUE;
-enc-rate_control.quality_eval_data.type = MJPEG_QUALITY_EVAL_TYPE_SET;
-enc-rate_control.quality_eval_data.reason = 
MJPEG_QUALITY_EVAL_REASON_RATE_CHANGE;
-enc-rate_control.warmup_start_time = ((uint64_t) time.tv_sec) * 
10 + time.tv_nsec;
-} else {
-enc-cbs.get_roundtrip_ms = NULL;
-mjpeg_encoder_reset_quality(enc, MJPEG_LEGACY_STATIC_QUALITY_ID, 
MJPEG_MAX_FPS, 0);
-}
-
-enc-cinfo.err = jpeg_std_error(enc-jerr);
-jpeg_create_compress(enc-cinfo);
-
-return enc;
-}
-
-void mjpeg_encoder_destroy(MJpegEncoder *encoder

[Spice-devel] [PATCH spice 02/13] server: Add a GStreamer 0.10 MJPEG video encoder and use it by default. (take 4)

2015-07-21 Thread Francois Gouget
The GStreamer video encoder supports both regular and sized streams.
It is otherwise quite basic and lacks any rate control: the bitrate is set at 
startup and will not react to changes in the network conditions. Still it 
should work fine on LANs.

Signed-off-by: Francois Gouget fgou...@codeweavers.com
---

Changes since take 3:
 - Failing to create the pipeline is probably a permanent issue so if 
   that happens encode_frame() now returns 
   VIDEO_ENCODER_FRAME_UNSUPPORTED so that Spice falls back to the 
   non-stream way of sending screen updates.

 - The video encoder will not get a zero bit rate so I removed handling 
   of that case. The bit rate floor has been raised to 128kbps. Going 
   below that does not seem very meaningful. Calculating the bit rate 
   ceiling has been moved to the get_bit_rate_cap() function.

 - Removed some redundant field initializations and added a comment.

 - Added a get_mbps() helper to simplify printing bandwidth values.

 - Some reformating and reordering to group related functions.

Changes since take 2:
 - I resolved the buffer timestamping issues. Appsrc is no longer a live 
   source (it had no reason to be) and it performs the timestamping. The 
   only remaining annoyance is that ffenc_mjpeg requires removing the 
   pipeline's default clock otherwise it gets stuck with the following 
   message:

   ERROR  ffmpeg :0:: Error, Invalid timestamp=0, last=0

   I consider this to be an ffenc_mjpeg bug since none of the other 
   encoders (VP8, H264 and even avenc_mpjpeg in GStreamer 1.0) has this 
   issue. So I'm keeping the clock removal as a workaround for 
   ffenc_mjpeg.

 - I went back to ffmpegcolorspace because it's the standard way to do
   color conversion in GStreamer 0.10 (present in gst-plugins-base), 
   while autovideoconvert is only present in gst-plugins-bad which I 
   believe we don't depend on.

 - I simplified the source frame copy code (push_raw_frame()). It's also 
   ready for adding zero-copy once GStreamer 1.0 support is added.

 - I improved the autoconf GStreamer 0.10 detection: it's now possible 
   to require GStreamer support, or just let it be included if present. 
   This also paves the way for GStreamer 1.0.

 - Changed set_appsrc_caps() and construct_pipeline() to return a 
   gboolean since they only return TRUE/FALSE.

 - Fixed some formatting issues, mostly braces placement.

Changes since take 1:
 - The width/height comments are now correct in the previous patch of
   the series.

 - Fixed the pipeline reconfiguration (for video size changes) so it 
   still works if we have to fall back to rebuilding the pipeline from 
   scratch.

 - Added a comment suggesting to avoid copying the compressed buffer as 
   a future improvement. I think this will require changing the way the 
   output buffer is allocated though. So I'm leaving that for after the 
   basic support committed.

 configure.ac   |  26 +++
 server/Makefile.am |   8 +
 server/gstreamer_encoder.c | 451 +
 server/red_worker.c|  11 +-
 server/video_encoder.h |   6 +
 5 files changed, 500 insertions(+), 2 deletions(-)
 create mode 100644 server/gstreamer_encoder.c

diff --git a/configure.ac b/configure.ac
index 5b4caa4..ca91b5a 100644
--- a/configure.ac
+++ b/configure.ac
@@ -80,6 +80,30 @@ AS_IF([test x$enable_opengl != xno], [
 SPICE_CHECK_SMARTCARD([SMARTCARD])
 AM_CONDITIONAL(SUPPORT_SMARTCARD, test x$have_smartcard = xyes)
 
+AC_ARG_ENABLE(gstreamer,
+  AS_HELP_STRING([--enable-gstreamer=@:@auto/yes/no@:@],
+ [Enable GStreamer 0.10 support]),
+  [],
+  [enable_gstreamer=auto])
+
+if test x$enable_gstreamer != xno; then
+PKG_CHECK_MODULES(GSTREAMER_0_10, [gstreamer-0.10, gstreamer-app-0.10],
+  [enable_gstreamer=yes
+   have_gstreamer_0_10=yes],
+  [have_gstreamer_0_10=no])
+if test x$have_gstreamer_0_10 = xyes; then
+AC_SUBST(GSTREAMER_0_10_CFLAGS)
+AC_SUBST(GSTREAMER_0_10_LIBS)
+AS_VAR_APPEND([SPICE_REQUIRES], [ gstreamer-0.10 gstreamer-app-0.10])
+AC_DEFINE([HAVE_GSTREAMER_0_10], [1], [Define if supporting GStreamer 
0.10])
+elif test x$enable_gstreamer = xyes; then
+AC_MSG_ERROR([GStreamer 0.10 support requested but not found. You may 
set GSTREAMER_0_10_CFLAGS and GSTREAMER_0_10_LIBS to avoid the need to call 
pkg-config.])
+fi
+else
+have_gstreamer_0_10=no
+fi
+AM_CONDITIONAL(SUPPORT_GSTREAMER_0_10, test x$have_gstreamer_0_10 = xyes)
+
 AC_ARG_ENABLE([automated_tests],
   AS_HELP_STRING([--enable-automated-tests], [Enable automated 
tests using spicy-screenshot (part of spice--gtk)]),,
   [enable_automated_tests=no])
@@ -311,6 +335,8 @@ echo 
 
 Smartcard:${have_smartcard}
 
+GStreamer 0.10:   ${have_gstreamer_0_10}
+
 SASL

[Spice-devel] [PATCH protocol 04/13] Add support for the VP8 and H264 video codecs and for advertising supported video codecs. (take 4)

2015-07-21 Thread Francois Gouget
Clients that support multiple codecs should advertise the 
SPICE_DISPLAY_CAP_MULTI_CODEC capability and one SPICE_DISPLAY_CAP_CODEC_XXX 
per supported codec.
---

This should be followed by a spice-common commit that ensures we get the 
right version of these headers (possibly that commit could be part of 
the commit of 03/13).

Changes since take 3:
 - None

Changes since take 2:
 - This patch also adds h264.

 spice/enums.h| 2 ++
 spice/protocol.h | 4 
 2 files changed, 6 insertions(+)

diff --git a/spice/enums.h b/spice/enums.h
index 6a0ab0b..36b0ea3 100644
--- a/spice/enums.h
+++ b/spice/enums.h
@@ -139,6 +139,8 @@ typedef enum SpicePathFlags {
 
 typedef enum SpiceVideoCodecType {
 SPICE_VIDEO_CODEC_TYPE_MJPEG = 1,
+SPICE_VIDEO_CODEC_TYPE_VP8,
+SPICE_VIDEO_CODEC_TYPE_H264,
 
 SPICE_VIDEO_CODEC_TYPE_ENUM_END
 } SpiceVideoCodecType;
diff --git a/spice/protocol.h b/spice/protocol.h
index d3c5962..614dcf1 100644
--- a/spice/protocol.h
+++ b/spice/protocol.h
@@ -135,6 +135,10 @@ enum {
 SPICE_DISPLAY_CAP_STREAM_REPORT,
 SPICE_DISPLAY_CAP_LZ4_COMPRESSION,
 SPICE_DISPLAY_CAP_PREF_COMPRESSION,
+SPICE_DISPLAY_CAP_MULTI_CODEC,
+SPICE_DISPLAY_CAP_CODEC_MJPEG,
+SPICE_DISPLAY_CAP_CODEC_VP8,
+SPICE_DISPLAY_CAP_CODEC_H264,
 };
 
 enum {
-- 
2.1.4
___
Spice-devel mailing list
Spice-devel@lists.freedesktop.org
http://lists.freedesktop.org/mailman/listinfo/spice-devel


[Spice-devel] [PATCH spice 05/13] server: Add VP8 support, a video codec preference list and compatibility checks with the Spice client. (take 4)

2015-07-21 Thread Francois Gouget
The video encoder preferences can be expressed by building a semi-colon 
separated list of encoder:codec pairs. For instance 'gstreamer:vp8;spice:mjpeg' 
to pick first the GStreamer VP8 video encoder first and used the original MJPEG 
video encoder one as a fallback.
The server has a default preference list which can also be selected by 
specifying 'auto' as the preferences list.
The client compatibility check relies on the following new 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, for now MJPEG 
and VP8.

Signed-off-by: Francois Gouget fgou...@codeweavers.com
---

Note that this patch depends on the 03/13 and 04/13 spice-common 
submodule patches.

Changes since take 3:
 - Proper fallback in case the server and client have no video codec 
   in common.

 - Check whether g_get_num_processors() is available for compatibility 
   with glib 2.35 and older.

Changes since take 2:
 - We now allow the VP8 encoder to produce P frames since this does not 
   increase the latency (i.e. it still lets us get the compressed frames 
   right away), while improving the compression ratio.

 - It turns out the above also helps with CPU usage and lets us 
   further configure the encoder for speed.

 - Only construct_pipeline() really needs to know the encoder name so 
   we no longer keep it in a GstEncoder field.

 - Fixed some formatting issues, mostly braces placement.

Changes since take 1:
 - Only set the parameters supported by the current encoder.

 - reconfigure_pipeline() handling has been fixed in the previous patch.

 - The video codecs list now has a more sensible default and it's 
   possible to explicitly request this default by specifying 'auto' in 
   the configuration files.


 configure.ac   |   4 ++
 server/gstreamer_encoder.c |  66 ++---
 server/mjpeg_encoder.c |   7 +-
 server/red_dispatcher.c| 172 -
 server/red_dispatcher.h|   8 +++
 server/red_worker.c|  82 +
 server/red_worker.h|  18 +
 server/reds.c  |  12 
 server/spice-server.h  |   1 +
 server/spice-server.syms   |   1 +
 server/video_encoder.h |  18 +++--
 11 files changed, 343 insertions(+), 46 deletions(-)

diff --git a/configure.ac b/configure.ac
index ca91b5a..e5be699 100644
--- a/configure.ac
+++ b/configure.ac
@@ -136,6 +136,10 @@ AS_IF([test x$have_smartcard = xyes], [
 PKG_CHECK_MODULES([GLIB2], [glib-2.0 = 2.22])
 AS_VAR_APPEND([SPICE_REQUIRES], [ glib-2.0 = 2.22])
 
+AC_CHECK_LIB(glib-2.0, g_get_num_processors,
+ AC_DEFINE([HAVE_G_GET_NUMPROCESSORS], 1, [Defined if we have 
g_get_num_processors()]),,
+ $GLIB2_LIBS)
+
 PKG_CHECK_MODULES(PIXMAN, pixman-1 = 0.17.7)
 AC_SUBST(PIXMAN_CFLAGS)
 AC_SUBST(PIXMAN_LIBS)
diff --git a/server/gstreamer_encoder.c b/server/gstreamer_encoder.c
index 8a21ad0..140261e 100644
--- a/server/gstreamer_encoder.c
+++ b/server/gstreamer_encoder.c
@@ -190,10 +190,27 @@ static gboolean set_appsrc_caps(GstEncoder *encoder)
 /* A helper for gst_encoder_encode_frame(). */
 static gboolean construct_pipeline(GstEncoder *encoder, const SpiceBitmap 
*bitmap)
 {
+gboolean no_clock = FALSE;
+const gchar* gstenc_name;
+switch (encoder-base.codec_type)
+{
+case SPICE_VIDEO_CODEC_TYPE_MJPEG:
+gstenc_name = ffenc_mjpeg;
+no_clock = TRUE;
+break;
+case SPICE_VIDEO_CODEC_TYPE_VP8:
+gstenc_name = vp8enc;
+break;
+default:
+spice_warning(unsupported codec type %d, encoder-base.codec_type);
+return FALSE;
+}
+
 GError *err = NULL;
-const gchar* desc = appsrc name=src format=2 do-timestamp=true ! 
ffmpegcolorspace ! ffenc_mjpeg name=encoder ! appsink name=sink;
+gchar *desc = g_strdup_printf(appsrc name=src format=2 do-timestamp=true 
! ffmpegcolorspace ! %s name=encoder ! appsink name=sink, gstenc_name);
 spice_debug(GStreamer pipeline: %s, desc);
 encoder-pipeline = gst_parse_launch_full(desc, NULL, 
GST_PARSE_FLAG_FATAL_ERRORS, err);
+g_free(desc);
 if (!encoder-pipeline) {
 spice_warning(GStreamer error: %s, err-message);
 g_clear_error(err);
@@ -203,19 +220,36 @@ static gboolean construct_pipeline(GstEncoder *encoder, 
const SpiceBitmap *bitma
 encoder-gstenc = gst_bin_get_by_name(GST_BIN(encoder-pipeline), 
encoder);
 encoder-appsink = 
GST_APP_SINK(gst_bin_get_by_name(GST_BIN(encoder-pipeline), sink));
 
+/* Configure the encoders for a zero-frame latency, and real-time speed */
+adjust_bit_rate(encoder);
+g_object_set(G_OBJECT(encoder-gstenc), bitrate, encoder-bit_rate, 
NULL);
+if (encoder-base.codec_type == SPICE_VIDEO_CODEC_TYPE_VP8

[Spice-devel] [PATCH 00/13] Add GStreamer support for video streams (take 4)

2015-07-21 Thread Francois Gouget

This follows up on the previous patch series with the addition of full 
bit rate support. This brings the GStreamer video encoder to feature 
parity with the builtin Spice MJPEG one so I think it's ready to be 
committed.

To summarize the changes since the last round:
 - The bit rate is automatically adjusted based on the network 
   conditions, both down and up.

 - Zero-copy for the compressed output buffer.

 - Proper fallback in case the server and client have no video codec in 
   common (which would only happen if the client does not support MJPEG 
   streams).


As for the previous round I'm only sending the patches needed for the 
Spice server to limit the size of this series. The GStreamer MJPEG 
encoder is fully compatible with existing clients so this should not 
hinder testing. I will post a new spice-gtk patch series soon but in the 
meantime one can fetch patches from GitHub to test the VP8 and h264 
codecs. See the gst branch of the repositories below:

spice:  https://github.com/fgouget/spice
spice-gtk:  https://github.com/fgouget/spice-gtk
xf86-video-qxl: https://github.com/fgouget/xf86-video-qxl

spice-common:   https://github.com/fgouget/spice-common
spice-protocol: https://github.com/fgouget/spice-protocol

(there's also 'extras' branches with more experimental/future patches 
for the curious)

For spice-html5 and QEMU one would have to refer to the patches posted 
previously on spice-devel. They should still work with this series.

Let me know if there are changes that are needed for inclusion. 


-- 
Francois Gouget fgou...@codeweavers.com
___
Spice-devel mailing list
Spice-devel@lists.freedesktop.org
http://lists.freedesktop.org/mailman/listinfo/spice-devel


[Spice-devel] [PATCH common 03/13] spice.proto: Add support for the VP8 and h264 video codecs. (take 4)

2015-07-21 Thread Francois Gouget
---

Changes since take 3:
 - None

Changes since take 2:
 - This patch also adds h264.

 spice.proto | 2 ++
 1 file changed, 2 insertions(+)

diff --git a/spice.proto b/spice.proto
index 4ea1263..fa4d448 100644
--- a/spice.proto
+++ b/spice.proto
@@ -329,6 +329,8 @@ flags8 path_flags { /* TODO: C enum names changes */
 
 enum8 video_codec_type {
 MJPEG = 1,
+VP8,
+H264,
 };
 
 flags8 stream_flags {
-- 
2.1.4

___
Spice-devel mailing list
Spice-devel@lists.freedesktop.org
http://lists.freedesktop.org/mailman/listinfo/spice-devel


[Spice-devel] [PATCH spice 11/13] server: Add h264 support to the GStreamer video encoder. (take 4)

2015-07-21 Thread Francois Gouget
Signed-off-by: Francois Gouget fgou...@codeweavers.com
---

Having support for h264 is interesting in its own right but this shows 
adding extra codecs is quite easy.


Changes since take 3:
 - None.


 server/gstreamer_encoder.c | 17 -
 server/red_dispatcher.c|  2 ++
 2 files changed, 18 insertions(+), 1 deletion(-)

diff --git a/server/gstreamer_encoder.c b/server/gstreamer_encoder.c
index 2ad1890..52b3e03 100644
--- a/server/gstreamer_encoder.c
+++ b/server/gstreamer_encoder.c
@@ -266,6 +266,9 @@ static gboolean construct_pipeline(GstEncoder *encoder, 
const SpiceBitmap *bitma
 case SPICE_VIDEO_CODEC_TYPE_VP8:
 gstenc_name = vp8enc;
 break;
+case SPICE_VIDEO_CODEC_TYPE_H264:
+gstenc_name = x264enc;
+break;
 default:
 spice_warning(unsupported codec type %d, encoder-base.codec_type);
 return FALSE;
@@ -322,6 +325,17 @@ static gboolean construct_pipeline(GstEncoder *encoder, 
const SpiceBitmap *bitma
  NULL);
 break;
 }
+case SPICE_VIDEO_CODEC_TYPE_H264:
+g_object_set(G_OBJECT(encoder-gstenc),
+ bitrate, encoder-bit_rate / 1024,
+ byte-stream, TRUE,
+ aud, FALSE,
+ tune, 4, /* Zero latency */
+ intra-refresh, TRUE,
+ sliced-threads, TRUE,
+ speed-preset, 1, /* ultrafast */
+ NULL);
+break;
 default:
 spice_warning(unknown encoder type %d, encoder-base.codec_type);
 reset_pipeline(encoder);
@@ -674,7 +688,8 @@ GstEncoder *create_gstreamer_encoder(SpiceVideoCodecType 
codec_type, uint64_t st
 
 spice_assert(!cbs || (cbs  cbs-get_roundtrip_ms  
cbs-get_source_fps));
 if (codec_type != SPICE_VIDEO_CODEC_TYPE_MJPEG 
-codec_type != SPICE_VIDEO_CODEC_TYPE_VP8) {
+codec_type != SPICE_VIDEO_CODEC_TYPE_VP8 
+codec_type != SPICE_VIDEO_CODEC_TYPE_H264) {
 spice_warning(unsupported codec type %d, codec_type);
 return NULL;
 }
diff --git a/server/red_dispatcher.c b/server/red_dispatcher.c
index d896d00..14d3f86 100644
--- a/server/red_dispatcher.c
+++ b/server/red_dispatcher.c
@@ -268,12 +268,14 @@ static create_video_encoder_proc video_encoder_procs[] = {
 static const EnumNames video_codec_names[] = {
 {SPICE_VIDEO_CODEC_TYPE_MJPEG, mjpeg},
 {SPICE_VIDEO_CODEC_TYPE_VP8, vp8},
+{SPICE_VIDEO_CODEC_TYPE_H264, h264},
 {0, NULL},
 };
 
 static const EnumNames video_cap_names[] = {
 {SPICE_DISPLAY_CAP_CODEC_MJPEG, mjpeg},
 {SPICE_DISPLAY_CAP_CODEC_VP8, vp8},
+{SPICE_DISPLAY_CAP_CODEC_H264, h264},
 {0, NULL},
 };
 
-- 
2.1.4

___
Spice-devel mailing list
Spice-devel@lists.freedesktop.org
http://lists.freedesktop.org/mailman/listinfo/spice-devel


[Spice-devel] [PATCH spice 09/13] server: Add GStreamer 1.0 support to the GStreamer video encoder. (take 4)

2015-07-21 Thread Francois Gouget
Signed-off-by: Francois Gouget fgou...@codeweavers.com
---

By default GStreamer 1.0 is used if available, otherwise GStreamer 0.10 
is used and Spice is compiled without GStreamer support as a last 
resort. It's possible to explicitly require a specific Gstreamer version 
with --enable-gstreamer=1.0 and --enable-gstreamer=0.10, or for any 
version with --enable-gstreamer=yes.

If you get an error while building the pipeline for MJPEG, then it 
probably means you need the fix for this bug:
https://bugzilla.gnome.org/show_bug.cgi?id=750398

Changes since take 3:
 - Check whether g_get_num_processors() is available for compatibility
   with glib 2.35 and older.

 - avenc_mjpeg needs the clock to be removed just like ffenc_mjpeg, its 
   0.10 counterpart.

 - Support for the new output buffer handling.


 configure.ac   | 35 +++
 server/Makefile.am | 12 +--
 server/gstreamer_encoder.c | 84 +-
 server/red_dispatcher.c|  2 +-
 4 files changed, 116 insertions(+), 17 deletions(-)

diff --git a/configure.ac b/configure.ac
index e5be699..702cd49 100644
--- a/configure.ac
+++ b/configure.ac
@@ -81,14 +81,32 @@ SPICE_CHECK_SMARTCARD([SMARTCARD])
 AM_CONDITIONAL(SUPPORT_SMARTCARD, test x$have_smartcard = xyes)
 
 AC_ARG_ENABLE(gstreamer,
-  AS_HELP_STRING([--enable-gstreamer=@:@auto/yes/no@:@],
- [Enable GStreamer 0.10 support]),
+  AS_HELP_STRING([--enable-gstreamer=@:@auto/0.10/1.0/yes/no@:@],
+ [Enable GStreamer support]),
   [],
   [enable_gstreamer=auto])
 
-if test x$enable_gstreamer != xno; then
+if test x$enable_gstreamer != xno  test x$enable_gstreamer != x0.10; 
then
+PKG_CHECK_MODULES(GSTREAMER_1_0, [gstreamer-1.0, gstreamer-app-1.0],
+  [enable_gstreamer=1.0
+   have_gstreamer_1_0=yes],
+  [have_gstreamer_1_0=no])
+if test x$have_gstreamer_1_0 = xyes; then
+AC_SUBST(GSTREAMER_1_0_CFLAGS)
+AC_SUBST(GSTREAMER_1_0_LIBS)
+AS_VAR_APPEND([SPICE_REQUIRES], [ gstreamer-1.0 gstreamer-app-1.0])
+AC_DEFINE([HAVE_GSTREAMER_1_0], [1], [Define if supporting GStreamer 
1.0])
+elif test x$enable_gstreamer = x1.0; then
+AC_MSG_ERROR([GStreamer 1.0 support requested but not found. You may 
set GSTREAMER_1_0_CFLAGS and GSTREAMER_1_0_LIBS to avoid the need to call 
pkg-config.])
+fi
+else
+have_gstreamer_1_0=no
+fi
+AM_CONDITIONAL(SUPPORT_GSTREAMER_1_0, test x$have_gstreamer_1_0 = xyes)
+
+if test x$enable_gstreamer != xno  test x$enable_gstreamer != x1.0; 
then
 PKG_CHECK_MODULES(GSTREAMER_0_10, [gstreamer-0.10, gstreamer-app-0.10],
-  [enable_gstreamer=yes
+  [enable_gstreamer=0.10
have_gstreamer_0_10=yes],
   [have_gstreamer_0_10=no])
 if test x$have_gstreamer_0_10 = xyes; then
@@ -96,7 +114,7 @@ if test x$enable_gstreamer != xno; then
 AC_SUBST(GSTREAMER_0_10_LIBS)
 AS_VAR_APPEND([SPICE_REQUIRES], [ gstreamer-0.10 gstreamer-app-0.10])
 AC_DEFINE([HAVE_GSTREAMER_0_10], [1], [Define if supporting GStreamer 
0.10])
-elif test x$enable_gstreamer = xyes; then
+elif test x$enable_gstreamer = x0.10; then
 AC_MSG_ERROR([GStreamer 0.10 support requested but not found. You may 
set GSTREAMER_0_10_CFLAGS and GSTREAMER_0_10_LIBS to avoid the need to call 
pkg-config.])
 fi
 else
@@ -104,6 +122,11 @@ else
 fi
 AM_CONDITIONAL(SUPPORT_GSTREAMER_0_10, test x$have_gstreamer_0_10 = xyes)
 
+if test x$enable_gstreamer = xyes; then
+AC_MSG_ERROR(GStreamer support requested but not found)
+fi
+AS_IF([test x$enable_gstreamer = xauto], [enable_gstreamer=no])
+
 AC_ARG_ENABLE([automated_tests],
   AS_HELP_STRING([--enable-automated-tests], [Enable automated 
tests using spicy-screenshot (part of spice--gtk)]),,
   [enable_automated_tests=no])
@@ -339,7 +362,7 @@ echo 
 
 Smartcard:${have_smartcard}
 
-GStreamer 0.10:   ${have_gstreamer_0_10}
+GStreamer:${enable_gstreamer}
 
 SASL support: ${enable_sasl}
 
diff --git a/server/Makefile.am b/server/Makefile.am
index 4921bc3..9fb0c8e 100644
--- a/server/Makefile.am
+++ b/server/Makefile.am
@@ -12,6 +12,7 @@ AM_CPPFLAGS = \
$(SLIRP_CFLAGS) \
$(SMARTCARD_CFLAGS) \
$(GSTREAMER_0_10_CFLAGS)\
+   $(GSTREAMER_1_0_CFLAGS) \
$(SSL_CFLAGS)   \
$(VISIBILITY_HIDDEN_CFLAGS) \
$(WARN_CFLAGS)  \
@@ -42,7 +43,8 @@ libspice_server_la_LIBADD =   
\
$(PIXMAN_LIBS

[Spice-devel] [PATCH spice 10/13] server: Avoid copying the input frame in the GStreamer encoder. (take 4)

2015-07-21 Thread Francois Gouget
To do so we reference the source bitmap chunks in the GStreamer buffer and rely 
on the buffer's lifetime being short enough.
Note that we can only avoid copies for the first 1 Mpixels or so. That's 
because Spice splits larger frames into more chunks and we can fit memory 
fragments inside a GStreamer buffer. So for those we will avoid copies for the 
first 3840 KB and copy the rest.

Signed-off-by: Francois Gouget fgou...@codeweavers.com
---

This makes it possible to avoid copying the source frame when using
GStreamer 1.0. Paradoxically we are still forced to do some copying for
the larger frames.

Here is how it works: Spice's frame buffer is composed of multiple 
memory chunks. So we use GStreamer's GstMemory objects to wrap each 
chunk and put them all to form the GstBuffer we pass to the pipeline. 
However there's a limit to the number of memory objects that we can put 
in a GstBuffer. Usually that limit is 16. Furthermore Spice splits the 
frame into 256KB chunks. so this approach only works up to 4MB or 
between 1 and 1.3Mpixels. For larger frames we use the zero-copy 
approach for the first 15 frame chunks, and copy all the rest into the 
16th memory chunk.

So on my machine, for a 720x304 video the frame copy time goes from 
around 265us (line-by-line) to 5us. For a 1440x900 frame it goes from 
about 1610us with the old line-by-line copy code, down to 1490us for the 
new chunk-by-chunk one, and down to about 440us when minimizing copies. 
The latter matches well with the ~0.3Mpixels we have to copy after the 
first 1Mpixels.

To avoid these copies it will be necessary to either increase the size 
of the Spice chunks or to increase the number of memory objects that 
GstBuffers can hold.

Changes since take 3:
 - None.

 server/gstreamer_encoder.c | 107 ++---
 1 file changed, 101 insertions(+), 6 deletions(-)

diff --git a/server/gstreamer_encoder.c b/server/gstreamer_encoder.c
index ac8f5c0..2ad1890 100644
--- a/server/gstreamer_encoder.c
+++ b/server/gstreamer_encoder.c
@@ -35,6 +35,10 @@ typedef struct GstEncoder GstEncoder;
 
 #define GSTE_DEFAULT_FPS 30
 
+#ifndef HAVE_GSTREAMER_0_10
+# define DO_ZERO_COPY
+#endif
+
 
 typedef struct {
 SpiceBitmapFmt  spice_format;
@@ -86,6 +90,11 @@ struct GstEncoder {
 /* The default video buffer */
 GstVideoBuffer *default_buffer;
 
+#ifdef DO_ZERO_COPY
+/* Set to TRUE until GStreamer no longer needs the raw bitmap buffer. */
+gboolean needs_bitmap;
+#endif
+
 /* The frame counter for GStreamer buffers */
 uint32_t frame;
 
@@ -355,6 +364,15 @@ static void reconfigure_pipeline(GstEncoder *encoder)
 }
 }
 
+#ifdef DO_ZERO_COPY
+/* A helper for push_raw_frame() */
+static void unref_bitmap(gpointer mem)
+{
+GstEncoder *encoder = (GstEncoder*)mem;
+encoder-needs_bitmap = FALSE;
+}
+#endif
+
 /* A helper for gst_encoder_encode_frame(). */
 static int push_raw_frame(GstEncoder *encoder, const SpiceBitmap *bitmap,
   const SpiceRect *src, int top_down)
@@ -362,15 +380,14 @@ static int push_raw_frame(GstEncoder *encoder, const 
SpiceBitmap *bitmap,
 const uint32_t stream_height = src-bottom - src-top;
 const uint32_t stream_stride = (src-right - src-left) * 
encoder-format-bpp / 8;
 uint32_t len = stream_stride * stream_height;
-GstBuffer *buffer = gst_buffer_new_and_alloc(len);
 #ifdef HAVE_GSTREAMER_0_10
+GstBuffer *buffer = gst_buffer_new_and_alloc(len);
 uint8_t *b = GST_BUFFER_DATA(buffer);
+uint8_t *dst = b;
 #else
-GstMapInfo map;
-gst_buffer_map(buffer, map, GST_MAP_WRITE);
-uint8_t *b = map.data;
+GstBuffer *buffer = gst_buffer_new();
+GstMapInfo map = { .memory = NULL };
 #endif
-uint8_t *dst = b;
 
 /* Note that we should not reorder the lines, even if top_down is false.
  * It just changes the number of lines to skip at the start of the bitmap.
@@ -382,6 +399,70 @@ static int push_raw_frame(GstEncoder *encoder, const 
SpiceBitmap *bitmap,
 
 if (stream_stride == bitmap-stride) {
 /* We can copy the bitmap chunk by chunk */
+#ifdef DO_ZERO_COPY
+/* We cannot control the lifetime of the bitmap but we can wrap it in
+ * the buffer anyway because:
+ * - Before returning from gst_encoder_encode_frame() we wait for the
+ *   pipeline to have converted this frame into a compressed buffer.
+ *   So it has to have gone through the frame at least once.
+ * - For all encoders but MJPEG, the first element of the pipeline will
+ *   convert the bitmap to another image format which entails copying
+ *   it. So by the time the encoder starts its work, this buffer will
+ *   not be needed anymore.
+ * - The MJPEG encoder does not perform inter-frame compression and 
thus
+ *   does not need to keep hold of this buffer once it has processed 
it.
+ */
+while (chunk_offset = chunks-chunk[chunk

[Spice-devel] [PATCH spice 12/13] server: Shape the bit rate of the GStreamer video encoders output.

2015-07-21 Thread Francois Gouget
The GStreamer encoders don't follow the specified bit rate very closely: they 
can decide to exceed it for ten seconds or more if they consider the scene 
deserves it. Such long bursts are enough to cause network congestion, resulting 
in long bouts of dropped frames.
So the GStreamer video encoder now uses a virtual buffer to shape the 
compressed video output and ensure we don't exceed the target bit rate for any 
significant length of time, which makes it possible to use higher bit rates 
overall.
It also keeps track of the encoded frame size so it can gather statistics and 
call update_client_playback_delay() with accurate information and also annotate 
the client report debug traces with the corresponding bit rate information.

Signed-off-by: Francois Gouget fgou...@codeweavers.com
---

The bit rate control code can be split into two parts:
 1. Code to turn the raw video into a compressed stream of the given bit rate.
 2. Feedback code that adjusts the bit rate based on the network conditions.

In theory the GStreamer encoders implement part 1 for us but, as stated 
in the commit message, in practice they are not strict enough (and most 
cannot be tweaked in this respect).

It's interesting to note that if the feedback mechanism gets good, 
timely information we can pretty much do without this patch: when 
GStreamer exceeds the set bit rate the feedback mechanism will notice a 
degradation of the network conditions and lower the target bit rate 
which will lower the GStreamer's output bit rate (even if it still 
exceeds the target bit rate a bit).

However this is suboptimal as it will force the feedback mechanism to 
either change the bit rate more frequently (causing a GStreamer pipeline 
reinitialization most of the time and degrading compression levels), or 
select a lower bit rate so the network capacity is not exceeded even if 
GStreamer goes 10 or 20% above the set target.

Also note that despite wanting to avoid exceeding the target bit rate, 
part 1 cannot consider frames individually, if only to correctly handle 
VP8's large I vs. P frame size discrepancy. Exceeding the target bit 
rate for sub-second periods generally does not cause network congestion 
hence the selection of a 300ms virtual buffer.


 server/gstreamer_encoder.c | 287 +++--
 1 file changed, 279 insertions(+), 8 deletions(-)

diff --git a/server/gstreamer_encoder.c b/server/gstreamer_encoder.c
index 52b3e03..4089ead 100644
--- a/server/gstreamer_encoder.c
+++ b/server/gstreamer_encoder.c
@@ -39,6 +39,9 @@ typedef struct GstEncoder GstEncoder;
 # define DO_ZERO_COPY
 #endif
 
+#define NANO_SECOND (10LL)
+#define MILLI_SECOND (1000LL)
+#define NANO_MS (NANO_SECOND / MILLI_SECOND)
 
 typedef struct {
 SpiceBitmapFmt  spice_format;
@@ -59,6 +62,11 @@ struct GstVideoBuffer {
 gboolean persistent;
 };
 
+typedef struct {
+uint32_t mm_time;
+uint32_t size;
+} GstFrameInformation;
+
 struct GstEncoder {
 VideoEncoder base;
 
@@ -98,11 +106,71 @@ struct GstEncoder {
 /* The frame counter for GStreamer buffers */
 uint32_t frame;
 
+
+/* -- Encoded frame statistics -- */
+
+/* Should be = than FRAME_STATISTICS_COUNT. This is also used to annotate
+ * the client report debug traces with bit rate information.
+ */
+#   define GSTE_HISTORY_SIZE 60
+
+/* A circular buffer containing the past encoded frames information. */
+GstFrameInformation history[GSTE_HISTORY_SIZE];
+
+/* The indices of the oldest and newest frames in the history buffer. */
+uint32_t history_first;
+uint32_t history_last;
+
+/* How many frames to take into account when computing the effective
+ * bit rate, average frame size, etc. This should be large enough so the
+ * I and P frames average out, and short enough for it to reflect the
+ * current situation.
+ */
+#   define GSTE_FRAME_STATISTICS_COUNT 21
+
+/* The index of the oldest frame taken into account for the statistics. */
+uint32_t stat_first;
+
+/* Used to compute the average frame size. */
+uint64_t stat_sum;
+
+/* Tracks the maximum frame size. */
+uint32_t stat_maximum;
+
+
+/* -- Encoder bit rate control --
+ *
+ * GStreamer encoders don't follow the specified bit rate very
+ * closely. These fields are used to ensure we don't exceed the desired
+ * stream bit rate, regardless of the GStreamer encoder's output.
+ */
+
 /* The bit rate target for the outgoing network stream. (bits per second) 
*/
 uint64_t bit_rate;
 
 /* The minimum bit rate */
 #   define GSTE_MIN_BITRATE (128 * 1024)
+
+/* The bit rate control is performed using a virtual buffer to allow short
+ * term variations: bursts are allowed until the virtual buffer is full.
+ * Then frames are dropped to limit the bit rate. VBUFFER_SIZE defines the
+ * size of the virtual buffer in milliseconds worth of data

[Spice-devel] [PATCH qxl 07/13] Xspice: Add a --video-codecs option to specify which encoder:codec to use. (take 4)

2015-07-21 Thread Francois Gouget
---

Changes since take 3:
 - None.

 scripts/Xspice | 3 ++-
 1 file changed, 2 insertions(+), 1 deletion(-)

diff --git a/scripts/Xspice b/scripts/Xspice
index 281535d..02875f5 100755
--- a/scripts/Xspice
+++ b/scripts/Xspice
@@ -86,6 +86,7 @@ parser.add_argument('--zlib-glz-wan-compression',
 # TODO - sound support
 parser.add_argument('--streaming-video', choices=['off', 'all', 'filter'],
 default='filter', help='filter by default')
+parser.add_argument('--video-codecs', help=Sets a semicolon-separated list of 
preferred video codecs to use. Each takes the form encoder:codec, with 
spice:mjpeg being the default and other options being provided by gstreamer for 
the mjpeg, vp8 and h264 codecs.)
 add_boolean('--ipv4-only')
 add_boolean('--ipv6-only')
 parser.add_argument('--vdagent', action='store_true', dest='vdagent_enabled', 
default=False, help='launch vdagent  vdagentd. They provide clipboard  
resolution automation')
@@ -251,7 +252,7 @@ var_args = ['port', 'tls_port', 'disable_ticketing',
 'x509_key_file', 'x509_key_password',
 'tls_ciphers', 'dh_file', 'password', 'image_compression',
 'jpeg_wan_compression', 'zlib_glz_wan_compression',
-'streaming_video', 'deferred_fps', 'exit_on_disconnect',
+'streaming_video', 'video_codecs', 'deferred_fps', 'exit_on_disconnect',
 'vdagent_enabled', 'vdagent_virtio_path', 'vdagent_uinput_path',
 'vdagent_uid', 'vdagent_gid']
 
-- 
2.1.4
___
Spice-devel mailing list
Spice-devel@lists.freedesktop.org
http://lists.freedesktop.org/mailman/listinfo/spice-devel


[Spice-devel] [PATCH qxl 06/13] spiceqxl: Add SpiceVideoCodecs and $XSPICE_VIDEO_CODECS for specifying video codec preferences. (take 4)

2015-07-21 Thread Francois Gouget
---

Changes since take 3:
 - None.

Changes since take 1:
 - Fixed a brace placement.

 examples/spiceqxl.xorg.conf.example |  7 +++
 src/qxl.h   |  1 +
 src/qxl_driver.c|  2 ++
 src/spiceqxl_spice_server.c | 15 +++
 4 files changed, 25 insertions(+)

diff --git a/examples/spiceqxl.xorg.conf.example 
b/examples/spiceqxl.xorg.conf.example
index d15f7f2..a82c2be 100644
--- a/examples/spiceqxl.xorg.conf.example
+++ b/examples/spiceqxl.xorg.conf.example
@@ -51,6 +51,13 @@ Section Device
 # defaults to filter.
 #Option SpiceStreamingVideo 
 
+# Set video codecs to use.  Provide a semicolon list of
+# codecs, in preference order.  Each codec requires an encoder
+# which can be one of spice or gstreamer, and then a codec type,
+# for instance mjpeg or vp8. The default is spice:mjpeg,
+# which uses the builtin mjpeg encoder.
+#Option SpiceVideoCodecs 
+
 # Set zlib glz wan compression. Options are auto, never, always.
 # defaults to auto.
 #Option SpiceZlibGlzWanCompression 
diff --git a/src/qxl.h b/src/qxl.h
index ff55604..5cc8d05 100644
--- a/src/qxl.h
+++ b/src/qxl.h
@@ -158,6 +158,7 @@ enum {
 OPTION_SURFACE_BUFFER_SIZE,
 OPTION_COMMAND_BUFFER_SIZE,
 OPTION_SPICE_SMARTCARD_FILE,
+OPTION_SPICE_VIDEO_CODECS,
 #endif
 OPTION_COUNT,
 };
diff --git a/src/qxl_driver.c b/src/qxl_driver.c
index ce0a88e..d036dac 100644
--- a/src/qxl_driver.c
+++ b/src/qxl_driver.c
@@ -155,6 +155,8 @@ const OptionInfoRec DefaultOptions[] =
   CommandBufferSize,OPTV_INTEGER,
{DEFAULT_COMMAND_BUFFER_SIZE}, FALSE},
 { OPTION_SPICE_SMARTCARD_FILE,
   SpiceSmartcardFile,   OPTV_STRING,{0}, FALSE},
+{ OPTION_SPICE_VIDEO_CODECS,
+  SpiceVideoCodecs, OPTV_STRING,{0}, FALSE},
 #endif
 
 { -1, NULL, OPTV_NONE, {0}, FALSE }
diff --git a/src/spiceqxl_spice_server.c b/src/spiceqxl_spice_server.c
index 14ee752..2f39561 100644
--- a/src/spiceqxl_spice_server.c
+++ b/src/spiceqxl_spice_server.c
@@ -173,6 +173,9 @@ void xspice_set_spice_server_options(OptionInfoPtr options)
 const char *streaming_video =
 get_str_option(options, OPTION_SPICE_STREAMING_VIDEO,
XSPICE_STREAMING_VIDEO);
+const char *video_codecs =
+get_str_option(options, OPTION_SPICE_VIDEO_CODECS,
+   XSPICE_VIDEO_CODECS);
 int agent_mouse =
 get_bool_option(options, OPTION_SPICE_AGENT_MOUSE,
 XSPICE_AGENT_MOUSE);
@@ -295,6 +298,18 @@ void xspice_set_spice_server_options(OptionInfoPtr options)
 spice_server_set_streaming_video(spice_server, streaming_video_opt);
 }
 
+if (video_codecs) {
+#if SPICE_SERVER_VERSION = 0x000c06 /* 0.12.6 */
+if (spice_server_set_video_codecs(spice_server, video_codecs)) {
+fprintf(stderr, spice: invalid video encoder %s\n, video_codecs);
+exit(1);
+}
+#else
+fprintf(stderr, spice: video_codecs are not available (spice = 
0.12.6 required)\n);
+exit(1);
+#endif
+}
+
 spice_server_set_agent_mouse
 (spice_server, agent_mouse);
 spice_server_set_playback_compression
-- 
2.1.4

___
Spice-devel mailing list
Spice-devel@lists.freedesktop.org
http://lists.freedesktop.org/mailman/listinfo/spice-devel


[Spice-devel] [PATCH spice 08/13] server: Let the video encoder manage the compressed buffer and avoid copying it.

2015-07-21 Thread Francois Gouget
This way the video encoder is not forced to use malloc()/free().
This also allows more flexibility in how the video encoder manages the buffer 
which allows for a zero-copy implementation in both video encoders.
The current implementations also ensure that there is no reallocation of the 
VideoBuffer structure.

Signed-off-by: Francois Gouget fgou...@codeweavers.com
---

This is a new patch which makes it possible to avoid copying the output 
buffer in the GStreamer video encoder.

Before:
 - Spice was handling the initial output buffer allocation, and was also 
   freeing it when destroying the stream.

 - When calling encode_frame() Spice knew that the buffer was no 
   longer needed for the previous frame. So it just reused it, saving on 
   reallocations.

 - The video encoder was responsible for reallocating the buffer when 
   needed. In the mjpeg_encoder case this was actually done by 
   the jpeg library, and thus out of the hands of the encoder itself.

 - The GStreamer pipeline allocates its own output buffer which forced 
   the video encoder to copy it to the Spice-provided output buffer.


Now:
 - The video encoders do all the output buffer allocations / 
   deallocations and give a pointer to the buffer to the rest of the 
   Spice code.

 - The video encoders could assume that the buffer is no longer used by 
   the time a new call to encode_frame() is made. But I prefer to 
   decouple this a bit more. So the Spice code is reponsible for 
   indicating when it no longer needs a given output buffer. This means 
   it could hold on to more than one output buffer at a time (for 
   buffering or whatever).

 - The video encoders optimize the case where the previous frame's 
   output buffer has been freed before the next encode_frame() call. 

 - The GStreamer video encoder can now pass the (wrapped) GStreamer 
   output buffer to the Spice code and thus avoid a copy. When Spice 
   releases the output buffer the corresponding GStreamer buffer it 
   released.


 server/gstreamer_encoder.c |  81 ++
 server/mjpeg_encoder.c | 106 +++--
 server/red_worker.c|  31 ++---
 server/video_encoder.h |  45 ---
 4 files changed, 187 insertions(+), 76 deletions(-)

diff --git a/server/gstreamer_encoder.c b/server/gstreamer_encoder.c
index 140261e..f7938ae 100644
--- a/server/gstreamer_encoder.c
+++ b/server/gstreamer_encoder.c
@@ -26,6 +26,8 @@
 
 #include red_common.h
 
+typedef struct GstVideoBuffer GstVideoBuffer;
+#define VIDEO_BUFFER_T GstVideoBuffer
 typedef struct GstEncoder GstEncoder;
 #define VIDEO_ENCODER_T GstEncoder
 #include video_encoder.h
@@ -44,6 +46,12 @@ typedef struct {
 int red_mask;
 } SpiceFormatForGStreamer;
 
+struct GstVideoBuffer {
+VideoBuffer base;
+GstBuffer *gst_buffer;
+gboolean persistent;
+};
+
 struct GstEncoder {
 VideoEncoder base;
 
@@ -72,6 +80,9 @@ struct GstEncoder {
 GstElement *gstenc;
 GstAppSink *appsink;
 
+/* The default video buffer */
+GstVideoBuffer *default_buffer;
+
 /* The frame counter for GStreamer buffers */
 uint32_t frame;
 
@@ -83,6 +94,35 @@ struct GstEncoder {
 };
 
 
+/* -- The GstVideoBuffer implementation -- */
+
+static inline GstVideoBuffer* gst_video_buffer_ref(GstVideoBuffer *buffer)
+{
+buffer-base.ref_count++;
+return buffer;
+}
+
+static void gst_video_buffer_unref(GstVideoBuffer *buffer)
+{
+if (--buffer-base.ref_count == 0) {
+gst_buffer_unref(buffer-gst_buffer);
+if (!buffer-persistent) {
+free(buffer);
+}
+}
+}
+
+static GstVideoBuffer* create_gst_video_buffer(gboolean persistent)
+{
+GstVideoBuffer *buffer = spice_new0(GstVideoBuffer, 1);
+buffer-base.ref = gst_video_buffer_ref;
+buffer-base.unref = gst_video_buffer_unref;
+buffer-persistent = persistent;
+buffer-base.ref_count = persistent ? 0 : 1;
+return buffer;
+}
+
+
 /* -- Miscellaneous GstEncoder helpers -- */
 
 static inline double get_mbps(uint64_t bit_rate)
@@ -358,24 +398,24 @@ static int push_raw_frame(GstEncoder *encoder, const 
SpiceBitmap *bitmap,
 }
 
 /* A helper for gst_encoder_encode_frame(). */
-static int pull_compressed_buffer(GstEncoder *encoder,
-  uint8_t **outbuf, size_t *outbuf_size,
-  int *data_size)
+static int pull_compressed_buffer(GstEncoder *encoder, GstVideoBuffer **buffer)
 {
-GstBuffer *buffer = gst_app_sink_pull_buffer(encoder-appsink);
-if (buffer) {
-int len = GST_BUFFER_SIZE(buffer);
-spice_assert(outbuf  outbuf_size);
-if (!*outbuf || *outbuf_size  len) {
-*outbuf = spice_realloc(*outbuf, len);
-*outbuf_size = len;
-}
-/* TODO Try to avoid this copy by changing the GstBuffer handling */
-memcpy(*outbuf, GST_BUFFER_DATA(buffer

[Spice-devel] [PATCH spice 13/13] server: Automatically adapt the GStreamer video encoder bit rate to the network conditions.

2015-07-21 Thread Francois Gouget
The video encoder uses the client reports and/or notifications of server frame 
drops as its feedback mechanisms.
It uses these to figure out the lowest bit rate that causes negative feedback, 
and the highest bit rate that allows a return to positive feedbacks. It then 
works to narrow this range and settles on the lower end once the spread has 
gone below a given threshold.
All the while it monitors the effective bit rate to ensure the target bit rate 
does not grow significantly beyond what the GStreamer encoder will produce.
As soon as the network feedback indicates a significant degradation the bit 
rate is lowered to minimize the risk of long freezes.
It also relies on the existing shaping of the GStreamer output bit rate to 
minimize the pipeline reconfigurations.

Signed-off-by: Francois Gouget fgou...@codeweavers.com
---

A word about the effective bit rate monitoring: when the video switches 
from high motion scenes to a mostly static talking head the GStreamer 
encoder may decide to save bits for later resulting in an effective bit 
rate that is half or less of its target. As a result all the network 
indicators will turn green, causing the bit rate control code to think 
the target can safely be increased. But increasing the target has no 
impact on the bit rate of the GStreamer output. So in such a situation 
it's possible to increase the target from 4Mbps to 20Mbps while the 
effective bit rate remains stuck at 2Mbps. But of course everything 
crumbles when the next action scene starts: then the GStreamer encoder 
will make full use of the 20Mbps, causing entwork congestion and the bit 
rate control algorithm will lose time halving the target bit rate 
multiple times before reaching values more in line with what the actual 
network capacity. Checking that the effective bit rate corresponds to 
the target before any increase avoids this issue.

The feedback mechanism mostly uses the video margin in the client stream 
reports. When all is good these are consistently close to the maximum 
value. So this forms a sort of buffer: when it's half empty or more the 
bit rate really must be reduced.

Regarding reacting to network congestion, there is always a lag between 
the congestion occuring and the video encoder being made aware of it, 
and then from there to the video encoder's actions having an effect. So 
it's important to react as quickly as possible so the network congestion 
does not escalate to dropped frames.
 - This means algorithms that operate on their own schedule, like every 
   20 frames, are proscribed.
 - Also server-side frame drops are systematically preceded by 
   client-side frame drops. So server-side frame drops must be acted on 
   immediately.

 server/gstreamer_encoder.c | 396 ++---
 1 file changed, 374 insertions(+), 22 deletions(-)

diff --git a/server/gstreamer_encoder.c b/server/gstreamer_encoder.c
index 4089ead..a46af7b 100644
--- a/server/gstreamer_encoder.c
+++ b/server/gstreamer_encoder.c
@@ -67,6 +67,12 @@ typedef struct {
 uint32_t size;
 } GstFrameInformation;
 
+enum GstBitRateStatus {
+GSTE_BITRATE_DECREASING,
+GSTE_BITRATE_INCREASING,
+GSTE_BITRATE_STABLE,
+};
+
 struct GstEncoder {
 VideoEncoder base;
 
@@ -106,6 +112,12 @@ struct GstEncoder {
 /* The frame counter for GStreamer buffers */
 uint32_t frame;
 
+/* The GStreamer bit rate. */
+uint64_t video_bit_rate;
+
+/* Don't bother changing the GStreamer bit rate if close enough. */
+#   define GSTE_VIDEO_BITRATE_MARGIN 0.05
+
 
 /* -- Encoded frame statistics -- */
 
@@ -140,7 +152,7 @@ struct GstEncoder {
 
 /* -- Encoder bit rate control --
  *
- * GStreamer encoders don't follow the specified bit rate very
+ * GStreamer encoders don't follow the specified video_bit_rate very
  * closely. These fields are used to ensure we don't exceed the desired
  * stream bit rate, regardless of the GStreamer encoder's output.
  */
@@ -148,7 +160,7 @@ struct GstEncoder {
 /* The bit rate target for the outgoing network stream. (bits per second) 
*/
 uint64_t bit_rate;
 
-/* The minimum bit rate */
+/* The minimum bit rate / bit rate increment. */
 #   define GSTE_MIN_BITRATE (128 * 1024)
 
 /* The bit rate control is performed using a virtual buffer to allow short
@@ -171,6 +183,89 @@ struct GstEncoder {
 
 /* How big of a margin to take to cover for latency jitter. */
 #   define GSTE_LATENCY_MARGIN 0.1
+
+
+/* -- Network bit rate control --
+ *
+ * State information for figuring out the optimal bit rate for the current
+ * network conditions.
+ */
+
+/* The mm_time of the last bit rate change. */
+uint32_t last_change;
+
+/* How much to reduce the bit rate in case of network congestion. */
+#   define GSTE_BITRATE_CUT 2
+#   define GSTE_BITRATE_REDUCE (4.0 / 3.0)
+
+/* Never increase the bit rate

[Spice-devel] [spice] server: spice_debug() messages don't need a trailing '\n'.

2015-07-15 Thread Francois Gouget
Signed-off-by: Francois Gouget fgou...@codeweavers.com
---
 server/red_dispatcher.c | 2 +-
 server/reds.c   | 4 ++--
 2 files changed, 3 insertions(+), 3 deletions(-)

diff --git a/server/red_dispatcher.c b/server/red_dispatcher.c
index fb8917a..88980ce 100644
--- a/server/red_dispatcher.c
+++ b/server/red_dispatcher.c
@@ -445,7 +445,7 @@ void 
red_dispatcher_client_monitors_config(VDAgentMonitorsConfig *monitors_confi
 !now-qxl-st-qif-client_monitors_config(now-qxl,
monitors_config)) {
 /* this is a normal condition, some qemu devices might not 
implement it */
-spice_debug(QXLInterface::client_monitors_config failed\n);
+spice_debug(QXLInterface::client_monitors_config failed);
 }
 now = now-next;
 }
diff --git a/server/reds.c b/server/reds.c
index d5f3d3a..552ddd8 100644
--- a/server/reds.c
+++ b/server/reds.c
@@ -1003,11 +1003,11 @@ static void reds_on_main_agent_monitors_config(
 msg_header = (VDAgentMessage *)cmc-buffer;
 if (sizeof(VDAgentMessage)  cmc-buffer_size ||
 msg_header-size  cmc-buffer_size - sizeof(VDAgentMessage)) {
-spice_debug(not enough data yet. %d\n, cmc-buffer_size);
+spice_debug(not enough data yet. %d, cmc-buffer_size);
 return;
 }
 monitors_config = (VDAgentMonitorsConfig *)(cmc-buffer + 
sizeof(*msg_header));
-spice_debug(%s: %d\n, __func__, monitors_config-num_of_monitors);
+spice_debug(%s: %d, __func__, monitors_config-num_of_monitors);
 red_dispatcher_client_monitors_config(monitors_config);
 reds_client_monitors_config_cleanup();
 }
-- 
2.1.4
___
Spice-devel mailing list
Spice-devel@lists.freedesktop.org
http://lists.freedesktop.org/mailman/listinfo/spice-devel


[Spice-devel] [spice 1/2] server: Don't reset the latency before showing it in the invalid net test error message.

2015-07-15 Thread Francois Gouget
Signed-off-by: Francois Gouget fgou...@codeweavers.com
---
 server/main_channel.c | 6 +++---
 1 file changed, 3 insertions(+), 3 deletions(-)

diff --git a/server/main_channel.c b/server/main_channel.c
index e7df3f9..f1b38af 100644
--- a/server/main_channel.c
+++ b/server/main_channel.c
@@ -969,11 +969,11 @@ static int main_channel_handle_parsed(RedChannelClient 
*rcc, uint32_t size, uint
 mcc-net_test_id = 0;
 if (roundtrip = mcc-latency) {
 // probably high load on client or server result with 
incorrect values
+spice_printerr(net test: invalid values, latency % PRIu64
+roundtrip % PRIu64 . assuming high
+bandwidth, mcc-latency, roundtrip);
 mcc-latency = 0;
 mcc-net_test_stage = NET_TEST_STAGE_INVALID;
-spice_printerr(net test: invalid values, latency % PRIu64
-roundtrip % PRIu64 . assuming high
-   bandwidth, mcc-latency, roundtrip);
 
red_channel_client_start_connectivity_monitoring(mcc-base,
  
CLIENT_CONNECTIVITY_TIMEOUT);
 break;
-- 
2.1.4

___
Spice-devel mailing list
Spice-devel@lists.freedesktop.org
http://lists.freedesktop.org/mailman/listinfo/spice-devel


[Spice-devel] [spice 2/2] server: Weakly try to get a better latency value for the bandwidth test.

2015-07-15 Thread Francois Gouget
Signed-off-by: Francois Gouget fgou...@codeweavers.com
---

NET_TEST_WARMUP_BYTES is 0 so the warmup ping is the same as the one we 
use to measure the latency. Even if it was not, the actual latency would 
be the MIN() of both anyway so we might as well use both roundtrip times 
to ward off latency jitter a bit.

 server/main_channel.c | 3 ++-
 1 file changed, 2 insertions(+), 1 deletion(-)

diff --git a/server/main_channel.c b/server/main_channel.c
index f1b38af..0df1751 100644
--- a/server/main_channel.c
+++ b/server/main_channel.c
@@ -959,11 +959,12 @@ static int main_channel_handle_parsed(RedChannelClient 
*rcc, uint32_t size, uint
 case NET_TEST_STAGE_WARMUP:
 mcc-net_test_id++;
 mcc-net_test_stage = NET_TEST_STAGE_LATENCY;
+mcc-latency = roundtrip;
 break;
 case NET_TEST_STAGE_LATENCY:
 mcc-net_test_id++;
 mcc-net_test_stage = NET_TEST_STAGE_RATE;
-mcc-latency = roundtrip;
+mcc-latency = MIN(mcc-latency, roundtrip);
 break;
 case NET_TEST_STAGE_RATE:
 mcc-net_test_id = 0;
-- 
2.1.4
___
Spice-devel mailing list
Spice-devel@lists.freedesktop.org
http://lists.freedesktop.org/mailman/listinfo/spice-devel


Re: [Spice-devel] [PATCH v6 08/26] server: Add VP8 support to the GStreamer encoder

2015-10-26 Thread Francois Gouget
On Thu, 22 Oct 2015, Christophe Fergeau wrote:

> On Wed, Oct 14, 2015 at 05:32:03PM +0200, Francois Gouget wrote:
> > The Spice server administrator can specify the preferred encoder and
> > codec preferences to optimize for CPU or bandwidth usage. Preferences
> > are described in a semi-colon separated list of encoder:codec pairs.
> > For instance 'gstreamer:vp8;spice:mjpeg' to pick first the GStreamer
> > VP8 video encoder and the original MJPEG video encoder as a fallback.
> > The server has a default preference list which can also be selected by
> > specifying 'auto' as the preferences list.
> 
> Note: All this paragraph describes a very different thing than what the
> shortlog says "server: Add VP8 support to the GStreamer encoder". Imo
> they are 2 distinct things, the addition of
> spice_server_set_video_codecs() and the addition of vp8 support to the
> gstreamer encoder, ie they should be (at least) 2 different commits. It
> might even make sense to move the client capability checks to a 3rd
> commit.

These are technically independent but conceptually they all depend on 
each other:
 * Adding VP8 support without a way to request using VP8 instead of 
   MJPEG would be equivalent to adding dead code. Furthermore if 
   compiling in GStreamer support forced use of VP8 then that server 
   would be incompatible with most clients so checking the client caps 
   is really necessary.

 * Committing a way to pick the encoder and codec when the only 
   codec is MJPEG does not make sense either. This could degenerate to 
   code that only lets the administrator pick the encoder (i.e. builting 
   or gstreamer), but the next patch would have to add support for the 
   codec and would essentially be just as big.

 * Committing the CAPS checking code first could work, though it would 
   be somewhat pointless and would not even shave a couple of lines off 
   this one.


> When adding use of SPICE_DISPLAY_CAP_MULTI_CODEC , I would raise the
> spice-protocol requirement in configure.ac to 0.12.11 (and do a
> post-release bump in spice-protocol git).

I have bumped the requirement to 0.12.11 in configure.ac but I believe 
the post-release bump in spice-protocol git has to be left to you.


> >  /* Start playing */
> >  spice_debug("setting state to PLAYING");
> > @@ -225,6 +274,12 @@ static gboolean construct_pipeline(SpiceGstEncoder 
> > *encoder,
> >  /* A helper for gst_encoder_encode_frame(). */
> >  static void reconfigure_pipeline(SpiceGstEncoder *encoder)
> >  {
> > +if (encoder->base.codec_type == SPICE_VIDEO_CODEC_TYPE_VP8) {
> > +/* vp8enc gets confused if we try to reconfigure the pipeline */
> > +reset_pipeline(encoder);
> > +return;
> > +}
> 
> Any bug reference for this one? Just add it to the comment if there is
> such a bug, if not, that's fine.

vp8enc ignores our attempt to change the appsrc caps so that when it 
gets a buffer of the wrong size we get stuck. Given that VP8 performs 
inter-frame compression I cannot totally blame it for not liking the 
video format to change mid-stream. So while I'd prefer it if it could 
deal with this case, I'm not sure this warrants a vp8enc bug report. In 
any case this requires a workaround for now. I tried to make the comment 
more explicit.

Here are the corresponding log traces:

(/usr/bin/Xorg:26752): Spice-Debug **: 
gstreamer_encoder.c:415:gst_encoder_encode_frame: video format change: width 0 
-> 640, height 0 -> 360, format 0 -> 9
[...]
(/usr/bin/Xorg:26752): Spice-Debug **: 
gstreamer_encoder.c:415:gst_encoder_encode_frame: video format change: width 
640 -> 764, height 360 -> 448, format 9 -> 9
[...]
0:00:00.343781738 26752 0x7f9768544050 DEBUG  basetransform 
gstbasetransform.c:624:gst_base_transform_transform_size: asked to 
transform size 1369088 for caps video/x-raw-rgb, bpp=(int)32, depth=(int)24, 
width=(int)640, height=(int)360, endianness=(int)4321, red_mask=(int)65280, 
green_mask=(int)16711680, blue_mask=(int)-16777216, framerate=(fraction)30/1 to 
size for caps video/x-raw-yuv, format=(fourcc)I420, width=(int)640, 
height=(int)360, framerate=(fraction)30/1 in direction SINK
** (Xorg:26752): WARNING **: ffmpegcsp0: size 1369088 is not a multiple of unit 
size 921600

See also:
http://lists.freedesktop.org/archives/spice-devel/2015-August/021274.html



> > @@ -1349,10 +1349,12 @@ static void mjpeg_encoder_get_stats(VideoEncoder 
> > *video_encoder,
> >  stats->avg_quality = (double)encoder->avg_quality / 
> > encoder->num_frames;
> >  }
> >  
> > -VideoEncoder *mjpeg_encoder_new(uint64_t starting_bit_rate,
> > +VideoEncoder *mjpeg_encoder_new(SpiceVideoCodecType codec_type,
> > +uint64_t start

Re: [Spice-devel] [PATCH v6 16/26] server: Give up after a while if GStreamer cannot handle the video

2015-10-26 Thread Francois Gouget
On Thu, 22 Oct 2015, Christophe Fergeau wrote:
[...]
> > @@ -1136,6 +1157,13 @@ static int gst_encoder_encode_frame(VideoEncoder 
> > *video_encoder,
> >  if (rc == VIDEO_ENCODER_FRAME_ENCODE_DONE) {
> >  rc = pull_compressed_buffer(encoder, video_buffer);
> >  #ifdef DO_ZERO_COPY
> > +if (rc != VIDEO_ENCODER_FRAME_ENCODE_DONE) {
> > +/* The input buffer will be stuck in the pipeline, preventing 
> > later
> > + * ones from being processed. So reset the pipeline.
> > + */
> > +reset_pipeline(encoder);
> > +encoder->errors++;
> 
> Maybe increase the errors in pull_compressed_buffer() ?

All the encoding errors eventually bubble up to 
gst_encoder_encode_frame() which is where they are caught, tallied and 
dealt with. So I think it makes more sense to keep that line here.


-- 
Francois Gouget <fgou...@codeweavers.com>
___
Spice-devel mailing list
Spice-devel@lists.freedesktop.org
http://lists.freedesktop.org/mailman/listinfo/spice-devel


Re: [Spice-devel] [PATCH v6 04/26] server: Hide the MJPEG encoder internals from red_worker.c

2015-10-21 Thread Francois Gouget
On Wed, 21 Oct 2015, Christophe Fergeau wrote:

> ACK.
> 
> Since the changes up to now are useful cleanups regardless of the
> addition of gstreamer, I suggest we land the patches up to this one
> right now, hopefully this will save some rebasing pain (haven't looked
> at rest of the patches yet, I'll do that now).

Thanks!

There's a couple others like this further down the patch series for 
spice-gtk:

 * [PATCH v6 20/26] spice-gtk: Prefix the configure audio GStreamer variables 
with GSTAUDIO_
   http://lists.freedesktop.org/archives/spice-devel/2015-October/022402.html

 * [PATCH v6 21/26] spice-gtk: Enable adding alternative video decoders
   This one actually received some comments and I split it in two and 
   sent the updated patches as attachments to my reply. The first part, 
   p21a.diff, is pretty short and would qualify as being independent 
   from the GStreamer rework.
   http://lists.freedesktop.org/archives/spice-devel/2015-October/022472.html
   
http://lists.freedesktop.org/archives/spice-devel/attachments/20151016/d2e54112/attachment.diff

   But sadly I have not gotten feedback on the modified patches yet so I 
   don't know if they are really fit to go.


-- 
Francois Gouget <fgou...@codeweavers.com>
___
Spice-devel mailing list
Spice-devel@lists.freedesktop.org
http://lists.freedesktop.org/mailman/listinfo/spice-devel


Re: [Spice-devel] [client 07/11] build-sys: Allow simultaneous support for Pulse and GStreamer audio

2015-11-08 Thread Francois Gouget
On Fri, 6 Nov 2015, Christophe Fergeau wrote:
[...]
> > -AC_ARG_WITH([audio],
> > -  AS_HELP_STRING([--with-audio=@<:@gstreamer/pulse/auto/no@:>@], [Select 
> > audio backend @<:@default=auto@:>@]),
> > +AC_ARG_ENABLE([pulse],
> > +  AS_HELP_STRING([--enable-pulse=@<:@yes/auto/no@:>@], [Enable the 
> > PulseAudio backend @<:@default=auto@:>@]),
> 
> Imo it would be a less disruptive change if we changed '--with-audio=auto' to
> enable both GStreamer and PulseAudio if the needed .pc files are
> available. Removing --with-audio and replacing it with
> --enable-pulseaudio/--enable-gstreamer means anyone using --with-audio
> will need to update its build scripts.

The drawback of --with-audio=auto is that it makes it impossible to 
require having support for both PulseAudio and GStreamer. That is unlike 
'./configure --enable-pulse --enable-gstaudio' it will not print an 
error if one of them is not available.

(and something like --with-audio=pulse,gstreamer feels wrong and would 
be very non standard)

Would keeping --with-audio as a temporary frontend for the two enable 
options be ok? It could print a warning to remind developers it's 
deprecated?

-- 
Francois Gouget <fgou...@codeweavers.com>

___
Spice-devel mailing list
Spice-devel@lists.freedesktop.org
http://lists.freedesktop.org/mailman/listinfo/spice-devel


Re: [Spice-devel] [common 03/11] build-sys: Add SPICE_CHECK_GSTREAMER_ELEMENTS()

2015-11-10 Thread Francois Gouget
On Wed, 4 Nov 2015, Christophe Fergeau wrote:
[...]
> > +AC_DEFUN([SPICE_CHECK_GSTREAMER_ELEMENTS], [
> > +AS_IF([test "x$1" != x],
> > +  [missing=""
> > +   for element in $3
> > +   do
> > +   AS_VAR_PUSHDEF([cache_var],[spice_cv_prog_${1}_${element}])dnl
> > +   AC_CACHE_CHECK([for the $element GStreamer element], cache_var,
> > +  [found=no
> > +   "$1" $element >/dev/null 2>/dev/null && 
> > found=yes
> > +   eval "cache_var=$found"])
> > +   AS_VAR_COPY(res, cache_var)
> 
> On el6, this needs a fallback definition:
> +m4_ifndef([AS_VAR_COPY],
> +  [m4_define([AS_VAR_COPY],
> +  [AS_LITERAL_IF([$1[]$2], [$1=$$2], [eval $1=\$$2])])])
> 
> I can add that before pushing. Looks good otherwise (though my m4-foo is
> weaker than what you are doing in this patch ;)

Thanks. That would be nice.

-- 
Francois Gouget <fgou...@codeweavers.com>
___
Spice-devel mailing list
Spice-devel@lists.freedesktop.org
http://lists.freedesktop.org/mailman/listinfo/spice-devel


Re: [Spice-devel] [spice 10/11] build-sys: Use AC_MSG_NOTICE()

2015-11-10 Thread Francois Gouget
On Tue, 3 Nov 2015, Francois Gouget wrote:

> Signed-off-by: Francois Gouget <fgou...@codeweavers.com>
> ---
>  configure.ac | 15 ---
>  1 file changed, 4 insertions(+), 11 deletions(-)
> 
> This patch is independent from all other patches in this series.

Is anything blocking this patch?


> diff --git a/configure.ac b/configure.ac
> index dfb967b..ad76467 100644
> --- a/configure.ac
> +++ b/configure.ac
> @@ -289,7 +289,7 @@ docs/manual/Makefile
>  ])
>  
>  dnl 
> ==
> -echo "
> +AC_MSG_NOTICE([
>  
>  Spice $VERSION
>  ==
> @@ -300,23 +300,16 @@ echo "
>  python:   ${PYTHON}
>  
>  OpenGL:   ${enable_opengl}
> -
>  LZ4 support:  ${enable_lz4}
> -
>  Smartcard:${have_smartcard}
> -
>  SASL support: ${enable_sasl}
> -
>  Automated tests:  ${enable_automated_tests}
> -
>  Manual:   ${have_asciidoc}
> -"
> +
> +Now type 'make' to build $PACKAGE
> +])
>  
>  if test x"$arch_warn" != x; then
>      AC_MSG_WARN([$arch_warn])
>  echo ""
>  fi
> -
> -echo \
> -"Now type 'make' to build $PACKAGE
> -"
> -- 
> 2.6.1


-- 
Francois Gouget <fgou...@codeweavers.com>
___
Spice-devel mailing list
Spice-devel@lists.freedesktop.org
http://lists.freedesktop.org/mailman/listinfo/spice-devel


Re: [Spice-devel] [client 04/11] build-sys: Remove some dead configure.ac DBus code

2015-11-10 Thread Francois Gouget
On Tue, 3 Nov 2015, Francois Gouget wrote:

> Signed-off-by: Francois Gouget <fgou...@codeweavers.com>
> ---
>  configure.ac | 4 
>  1 file changed, 4 deletions(-)
> 
> This patch does not depend on any other patch in this series.

Anything blocking this?
(there must be a curse...)


> diff --git a/configure.ac b/configure.ac
> index 5790a37..7033cbb 100644
> --- a/configure.ac
> +++ b/configure.ac
> @@ -671,10 +671,6 @@ have_dbus=no
>  if test "x$enable_dbus" != "xno"; then
>AC_DEFINE([USE_GDBUS], [1], [Define if supporting gdbus])
>have_dbus=yes
> -
> -  if test "x$enable_dbus" = "xyes" && test "x$have_dbus" = "xno"; then
> -AC_MSG_ERROR([D-Bus support explicitly requested, but some required 
> packages are not available])
> -  fi
>  fi
>  
>  SPICE_CHECK_LZ4
> -- 
> 2.6.1
> 
> ___
> Spice-devel mailing list
> Spice-devel@lists.freedesktop.org
> http://lists.freedesktop.org/mailman/listinfo/spice-devel
> 


-- 
Francois Gouget <fgou...@codeweavers.com>
___
Spice-devel mailing list
Spice-devel@lists.freedesktop.org
http://lists.freedesktop.org/mailman/listinfo/spice-devel


Re: [Spice-devel] [common 01/11] build-sys: Add the SPICE_WARNING() and SPICE_PRINT_MESSAGES m4 macros

2015-11-10 Thread Francois Gouget
On Tue, 3 Nov 2015, Francois Gouget wrote:

> A call to SPICE_WARNING() anywhere in the configure file results in the
> warning being printed at the end of the configure run where it will be
> be visible. This makes it possible to keep the SPICE_WARNING() calls
> together with the related feature checks instead of having to put a
> separate AC_MSG_WARN() call near the end.

This version has the AS_VAR_APPEND() fallback. Is it ok?


> 
> Signed-off-by: Francois Gouget <fgou...@codeweavers.com>
> ---
>  m4/spice-deps.m4 | 21 +
>  1 file changed, 21 insertions(+)
> 
> For reference, see also:
> http://lists.freedesktop.org/archives/spice-devel/2015-November/023009.html
> 
> diff --git a/m4/spice-deps.m4 b/m4/spice-deps.m4
> index 0f90cec..57d5b78 100644
> --- a/m4/spice-deps.m4
> +++ b/m4/spice-deps.m4
> @@ -1,3 +1,24 @@
> +# For autoconf < 2.63
> +m4_ifndef([AS_VAR_APPEND],
> +  AC_DEFUN([AS_VAR_APPEND], $1=$$1$2))
> +
> +# SPICE_WARNING(warning)
> +# SPICE_PRINT_MESSAGES
> +# --
> +# Collect warnings and print them at the end so they are clearly visible.
> +# -
> +AC_DEFUN([SPICE_WARNING],AS_VAR_APPEND([spice_warnings],["|$1"]))
> +AC_DEFUN([SPICE_PRINT_MESSAGES],[
> +ac_save_IFS="$IFS"
> +IFS="|"
> +for msg in $spice_warnings; do
> +IFS="$ac_save_IFS"
> +AS_VAR_IF([msg],[],,[AC_MSG_WARN([$msg]); echo >&2])
> +done
> +IFS="$ac_save_IFS"
> +])
> +
> +
>  # SPICE_CHECK_SYSDEPS()
>  # -
>  # Checks for header files and library functions needed by spice-common.
> -- 
> 2.6.1


-- 
Francois Gouget <fgou...@codeweavers.com>
___
Spice-devel mailing list
Spice-devel@lists.freedesktop.org
http://lists.freedesktop.org/mailman/listinfo/spice-devel


[Spice-devel] [spice v3] server: Provide a framerate estimate based on the initial frames

2015-11-13 Thread Francois Gouget
This way the video encoder can actually count on a real estimate when
it is initializing.

Signed-off-by: Francois Gouget <fgou...@codeweavers.com>
---
 server/display-channel.h |  1 +
 server/red_worker.c  | 18 ++
 server/stream.h  |  1 +
 3 files changed, 16 insertions(+), 4 deletions(-)

I sent this patch in June:
http://lists.freedesktop.org/archives/spice-devel/2015-June/thread.html

Then again a week ago:
http://lists.freedesktop.org/archives/spice-devel/2015-November/thread.html

But never got any feedback on it. What's up???


diff --git a/server/display-channel.h b/server/display-channel.h
index c3dcc29..24f9da5 100644
--- a/server/display-channel.h
+++ b/server/display-channel.h
@@ -152,6 +152,7 @@ struct Drawable {
 Ring glz_ring;
 
 red_time_t creation_time;
+red_time_t first_frame_time;
 int frames_count;
 int gradual_frames_count;
 int last_gradual_frame;
diff --git a/server/red_worker.c b/server/red_worker.c
index 9673288..b141a1e 100644
--- a/server/red_worker.c
+++ b/server/red_worker.c
@@ -984,6 +984,7 @@ static void 
display_stream_trace_add_drawable(DisplayChannel *display, Drawable
 
 trace = >items_trace[display->next_item_trace++ & 
ITEMS_TRACE_MASK];
 trace->time = item->creation_time;
+trace->first_frame_time = item->first_frame_time;
 trace->frames_count = item->frames_count;
 trace->gradual_frames_count = item->gradual_frames_count;
 trace->last_gradual_frame = item->last_gradual_frame;
@@ -1772,7 +1773,12 @@ static void display_channel_create_stream(DisplayChannel 
*display, Drawable *dra
 SpiceBitmap *bitmap = >red_drawable->u.copy.src_bitmap->u.bitmap;
 stream->top_down = !!(bitmap->flags & SPICE_BITMAP_FLAGS_TOP_DOWN);
 drawable->stream = stream;
-stream->input_fps = MAX_FPS;
+/* Provide an fps estimate the video encoder can use when initializing
+ * based on the frames that lead to the creation of the stream. Round to
+ * the nearest integer, for instance 24 for 23.976.
+ */
+uint64_t duration = drawable->creation_time - drawable->first_frame_time;
+stream->input_fps = ((uint64_t)drawable->frames_count * 1000 * 1000 * 1000 
+ duration / 2) / duration;
 stream->num_input_frames = 0;
 stream->input_fps_start_time = drawable->creation_time;
 display->streams_size_total += stream->width * stream->height;
@@ -1780,10 +1786,10 @@ static void 
display_channel_create_stream(DisplayChannel *display, Drawable *dra
 FOREACH_DCC(display, dcc_ring_item, next, dcc) {
 dcc_create_stream(dcc, stream);
 }
-spice_debug("stream %d %dx%d (%d, %d) (%d, %d)",
+spice_debug("stream %d %dx%d (%d, %d) (%d, %d) %u fps",
 (int)(stream - display->streams_buf), stream->width,
 stream->height, stream->dest_area.left, stream->dest_area.top,
-stream->dest_area.right, stream->dest_area.bottom);
+stream->dest_area.right, stream->dest_area.bottom, 
stream->input_fps);
 return;
 }
 
@@ -2009,11 +2015,13 @@ static int is_stream_start(Drawable *drawable)
 // returns whether a stream was created
 static int display_channel_stream_add_frame(DisplayChannel *display,
 Drawable *frame_drawable,
+red_time_t first_frame_time,
 int frames_count,
 int gradual_frames_count,
 int last_gradual_frame)
 {
 update_copy_graduality(display, frame_drawable);
+frame_drawable->first_frame_time = first_frame_time;
 frame_drawable->frames_count = frames_count + 1;
 frame_drawable->gradual_frames_count  = gradual_frames_count;
 
@@ -2074,6 +2082,7 @@ static void 
display_channel_stream_maintenance(DisplayChannel *display,
  FALSE);
 if (is_next_frame != STREAM_FRAME_NONE) {
 display_channel_stream_add_frame(display, candidate,
+ prev->first_frame_time,
  prev->frames_count,
  prev->gradual_frames_count,
  prev->last_gradual_frame);
@@ -2235,6 +2244,7 @@ static void red_use_stream_trace(DisplayChannel *display, 
Drawable *drawable)
>dest_area, trace->time, NULL, 
FALSE) !=
STREAM_FRAME_NONE) {
 if (display_channel_stream_add_frame(display, drawable,
+ trace->first_frame_time,
  trace->frames_

[Spice-devel] [spice] build-sys: Use AC_MSG_NOTICE()

2015-11-13 Thread Francois Gouget
Signed-off-by: Francois Gouget <fgou...@codeweavers.com>
---
 configure.ac | 15 ---
 1 file changed, 4 insertions(+), 11 deletions(-)

I submitted this very simple patch twice before as part of patch series 
while noting it was independent of the rest of the series:
http://lists.freedesktop.org/archives/spice-devel/2015-October/022911.html
http://lists.freedesktop.org/archives/spice-devel/2015-November/023057.html

Asked if something was wrong with it there:
http://lists.freedesktop.org/archives/spice-devel/2015-November/023368.html

One of the series it was in sort of got acked there:
http://lists.freedesktop.org/archives/spice-devel/2015-November/023144.html

Let's see if it fares any better when presented all on its own.


diff --git a/configure.ac b/configure.ac
index dfb967b..ad76467 100644
--- a/configure.ac
+++ b/configure.ac
@@ -289,7 +289,7 @@ docs/manual/Makefile
 ])
 
 dnl ==
-echo "
+AC_MSG_NOTICE([
 
 Spice $VERSION
 ==
@@ -300,23 +300,16 @@ echo "
 python:   ${PYTHON}
 
 OpenGL:   ${enable_opengl}
-
 LZ4 support:  ${enable_lz4}
-
 Smartcard:${have_smartcard}
-
 SASL support: ${enable_sasl}
-
 Automated tests:  ${enable_automated_tests}
-
 Manual:   ${have_asciidoc}
-"
+
+Now type 'make' to build $PACKAGE
+])
 
 if test x"$arch_warn" != x; then
 AC_MSG_WARN([$arch_warn])
 echo ""
 fi
-
-echo \
-"Now type 'make' to build $PACKAGE
-"
-- 
2.6.2

___
Spice-devel mailing list
Spice-devel@lists.freedesktop.org
http://lists.freedesktop.org/mailman/listinfo/spice-devel


[Spice-devel] [spice] server: Don't check the 'this' mjpeg_encoder pointer

2015-11-13 Thread Francois Gouget
mjpeg_encoder_get_stats() was the only function to check it.

Signed-off-by: Francois Gouget <fgou...@codeweavers.com>
---
 server/mjpeg_encoder.c | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/server/mjpeg_encoder.c b/server/mjpeg_encoder.c
index c8253a7..84a0078 100644
--- a/server/mjpeg_encoder.c
+++ b/server/mjpeg_encoder.c
@@ -1333,7 +1333,7 @@ uint64_t mjpeg_encoder_get_bit_rate(MJpegEncoder *encoder)
 
 void mjpeg_encoder_get_stats(MJpegEncoder *encoder, MJpegEncoderStats *stats)
 {
-spice_assert(encoder != NULL && stats != NULL);
+spice_assert(stats != NULL);
 stats->starting_bit_rate = encoder->starting_bit_rate;
 stats->cur_bit_rate = mjpeg_encoder_get_bit_rate(encoder);
 stats->avg_quality = (double)encoder->avg_quality / encoder->num_frames;
-- 
2.6.2
___
Spice-devel mailing list
Spice-devel@lists.freedesktop.org
http://lists.freedesktop.org/mailman/listinfo/spice-devel


[Spice-devel] [PATCH v2 1/3] vdagent: Group the client and server functions together

2015-11-13 Thread Francois Gouget
This will simplify selectively disabling the server-side code.

Signed-off-by: Francois Gouget <fgou...@codeweavers.com>
---
 src/udscs.c | 478 ++--
 src/udscs.h | 128 +---
 2 files changed, 314 insertions(+), 292 deletions(-)

I separated the reordering from the addition of the #ifdefs as suggested 
by Victor Toso:
http://lists.freedesktop.org/archives/spice-devel/2015-November/023457.html

diff --git a/src/udscs.c b/src/udscs.c
index 288aca2..732db33 100644
--- a/src/udscs.c
+++ b/src/udscs.c
@@ -66,86 +66,6 @@ struct udscs_connection {
 struct udscs_connection *prev;
 };
 
-struct udscs_server {
-int fd;
-const char * const *type_to_string;
-int no_types;
-int debug;
-struct udscs_connection connections_head;
-udscs_connect_callback connect_callback;
-udscs_read_callback read_callback;
-udscs_disconnect_callback disconnect_callback;
-};
-
-static void udscs_do_write(struct udscs_connection **connp);
-static void udscs_do_read(struct udscs_connection **connp);
-
-
-struct udscs_server *udscs_create_server(const char *socketname,
-udscs_connect_callback connect_callback,
-udscs_read_callback read_callback,
-udscs_disconnect_callback disconnect_callback,
-const char * const type_to_string[], int no_types, int debug)
-{
-int c;
-struct sockaddr_un address;
-struct udscs_server *server;
-
-server = calloc(1, sizeof(*server));
-if (!server)
-return NULL;
-
-server->type_to_string = type_to_string;
-server->no_types = no_types;
-server->debug = debug;
-
-server->fd = socket(PF_UNIX, SOCK_STREAM, 0);
-if (server->fd == -1) {
-syslog(LOG_ERR, "creating unix domain socket: %m");
-free(server);
-return NULL;
-}
-
-address.sun_family = AF_UNIX;
-snprintf(address.sun_path, sizeof(address.sun_path), "%s", socketname);
-c = bind(server->fd, (struct sockaddr *), sizeof(address));
-if (c != 0) {
-syslog(LOG_ERR, "bind %s: %m", socketname);
-free(server);
-return NULL;
-}
-
-c = listen(server->fd, 5);
-if (c != 0) {
-syslog(LOG_ERR, "listen: %m");
-free(server);
-return NULL;
-}
-
-server->connect_callback = connect_callback;
-server->read_callback = read_callback;
-server->disconnect_callback = disconnect_callback;
-
-return server;
-}
-
-void udscs_destroy_server(struct udscs_server *server)
-{
-struct udscs_connection *conn, *next_conn;
-
-if (!server)
-return;
-
-conn = server->connections_head.next;
-while (conn) {
-next_conn = conn->next;
-udscs_destroy_connection();
-conn = next_conn;
-}
-close(server->fd);
-free(server);
-}
-
 struct udscs_connection *udscs_connect(const char *socketname,
 udscs_read_callback read_callback,
 udscs_disconnect_callback disconnect_callback,
@@ -225,131 +145,17 @@ void udscs_destroy_connection(struct udscs_connection 
**connp)
 *connp = NULL;
 }
 
-struct ucred udscs_get_peer_cred(struct udscs_connection *conn)
-{
-return conn->peer_cred;
-}
-
-int udscs_server_fill_fds(struct udscs_server *server, fd_set *readfds,
-fd_set *writefds)
+void udscs_set_user_data(struct udscs_connection *conn, void *data)
 {
-struct udscs_connection *conn;
-int nfds = server->fd + 1;
-
-if (!server)
-return -1;
-
-FD_SET(server->fd, readfds);
-
-conn = server->connections_head.next;
-while (conn) {
-int conn_nfds = udscs_client_fill_fds(conn, readfds, writefds);
-if (conn_nfds > nfds)
-nfds = conn_nfds;
-
-conn = conn->next;
-}
-
-return nfds;
+conn->user_data = data;
 }
 
-int udscs_client_fill_fds(struct udscs_connection *conn, fd_set *readfds,
-fd_set *writefds)
+void *udscs_get_user_data(struct udscs_connection *conn)
 {
 if (!conn)
-return -1;
-
-FD_SET(conn->fd, readfds);
-if (conn->write_buf)
-FD_SET(conn->fd, writefds);
-
-return conn->fd + 1;
-}
-
-static void udscs_server_accept(struct udscs_server *server) {
-struct udscs_connection *new_conn, *conn;
-struct sockaddr_un address;
-socklen_t length = sizeof(address);
-int r, fd;
-
-fd = accept(server->fd, (struct sockaddr *), );
-if (fd == -1) {
-if (errno == EINTR)
-return;
-syslog(LOG_ERR, "accept: %m");
-return;
-}
-
-new_conn = calloc(1, sizeof(*conn));
-if (!new_conn) {
-syslog(LOG_ERR, "out of memory, disconnecting new client");
-close(fd);
-return;
-}
-
-new_conn->fd = fd;
-new_conn->type_to_string = server->type_to_string;
-new_conn->no_types = server->no_types;
-new_conn->debug 

[Spice-devel] [PATCH v2 3/3] vdagent: Disable the server-side udscs code for vdagent

2015-11-13 Thread Francois Gouget
vdagent only needs the client-side API.

Signed-off-by: Francois Gouget <fgou...@codeweavers.com>
---
 Makefile.am | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/Makefile.am b/Makefile.am
index 8c55b43..7def506 100644
--- a/Makefile.am
+++ b/Makefile.am
@@ -4,7 +4,7 @@ NULL =
 bin_PROGRAMS = src/spice-vdagent
 sbin_PROGRAMS = src/spice-vdagentd
 
-src_spice_vdagent_CFLAGS = $(X_CFLAGS) $(SPICE_CFLAGS) $(GLIB2_CFLAGS) 
$(ALSA_CFLAGS)
+src_spice_vdagent_CFLAGS = $(X_CFLAGS) $(SPICE_CFLAGS) $(GLIB2_CFLAGS) 
$(ALSA_CFLAGS) -DUDSCS_NO_SERVER
 src_spice_vdagent_LDADD = $(X_LIBS) $(SPICE_LIBS) $(GLIB2_LIBS) $(ALSA_LIBS)
 src_spice_vdagent_SOURCES = src/vdagent.c \
 src/vdagent-x11.c \
-- 
2.6.2
___
Spice-devel mailing list
Spice-devel@lists.freedesktop.org
http://lists.freedesktop.org/mailman/listinfo/spice-devel


[Spice-devel] [PATCH v2 2/3] vdagent: Allow disabling the server-side udscs support

2015-11-13 Thread Francois Gouget
To do so define UDSCS_NO_SERVER.
This simplifies reuse in client-only scenarios that don't need peer
credential support for instance.

Signed-off-by: Francois Gouget <fgou...@codeweavers.com>
---
 src/udscs.c | 8 +++-
 1 file changed, 7 insertions(+), 1 deletion(-)

diff --git a/src/udscs.c b/src/udscs.c
index 732db33..334d54a 100644
--- a/src/udscs.c
+++ b/src/udscs.c
@@ -46,8 +46,10 @@ struct udscs_connection {
 const char * const *type_to_string;
 int no_types;
 int debug;
-struct ucred peer_cred;
 void *user_data;
+#ifndef UDSCS_NO_SERVER
+struct ucred peer_cred;
+#endif
 
 /* Read stuff, single buffer, separate header and data buffer */
 int header_read;
@@ -350,6 +352,8 @@ int udscs_client_fill_fds(struct udscs_connection *conn, 
fd_set *readfds,
 }
 
 
+#ifndef UDSCS_NO_SERVER
+
 /* -- Server-side implementation -- */
 
 struct udscs_server {
@@ -563,3 +567,5 @@ int udscs_server_for_all_clients(struct udscs_server 
*server,
 }
 return r;
 }
+
+#endif
-- 
2.6.2

___
Spice-devel mailing list
Spice-devel@lists.freedesktop.org
http://lists.freedesktop.org/mailman/listinfo/spice-devel


[Spice-devel] [spice] server: Remove the display_channel_attach_stream() prototype

2015-11-13 Thread Francois Gouget
It is unused.

Signed-off-by: Francois Gouget <fgou...@codeweavers.com>
---
 server/display-channel.h | 3 ---
 1 file changed, 3 deletions(-)

It was added in this commit:

commit 4987df8e67f48cde13d39f4e81909f672ae33e29
Author: Marc-André Lureau <marcandre.lur...@gmail.com>
Date:   Tue Nov 10 13:21:28 2015 +

worker: move stream to display channel

Acked-by: Jonathon Jongsma <jjong...@redhat.com>

So unless there was some ulterior motive it should not be there.

diff --git a/server/display-channel.h b/server/display-channel.h
index c3dcc29..a9ae40a 100644
--- a/server/display-channel.h
+++ b/server/display-channel.h
@@ -358,9 +358,6 @@ typedef struct SurfaceCreateItem {
 
 void   display_channel_set_stream_video  
(DisplayChannel *display,
   int 
stream_video);
-void   display_channel_attach_stream 
(DisplayChannel *display,
-  Drawable 
*drawable,
-  Stream 
*stream);
 intdisplay_channel_get_streams_timeout   
(DisplayChannel *display);
 void   display_channel_compress_stats_print  (const 
DisplayChannel *display);
 void   display_channel_compress_stats_reset  
(DisplayChannel *display);
-- 
2.6.2___
Spice-devel mailing list
Spice-devel@lists.freedesktop.org
http://lists.freedesktop.org/mailman/listinfo/spice-devel


[Spice-devel] vdagent: VDP_LAST_PORT is redundant with VDP_END_PORT. Remove it

2015-11-13 Thread Francois Gouget
VDP_LAST_PORT is equal to VDP_SERVER_PORT while VDP_END_PORT (defined
in spice-protocol) is VDP_SERVER_PORT + 1 so the code needs to be
adjusted to account for this difference.

Signed-off-by: Francois Gouget <fgou...@codeweavers.com>
---
 src/vdagent-virtio-port.c | 9 -
 1 file changed, 4 insertions(+), 5 deletions(-)

Adjusted the commit log as suggested by Christophe Fergeau:
http://lists.freedesktop.org/archives/spice-devel/2015-November/023297.html


diff --git a/src/vdagent-virtio-port.c b/src/vdagent-virtio-port.c
index b04d55b..722f3ba 100644
--- a/src/vdagent-virtio-port.c
+++ b/src/vdagent-virtio-port.c
@@ -31,7 +31,6 @@
 
 #include "vdagent-virtio-port.h"
 
-#define VDP_LAST_PORT VDP_SERVER_PORT
 
 struct vdagent_virtio_port_buf {
 uint8_t *buf;
@@ -63,7 +62,7 @@ struct vdagent_virtio_port {
 uint8_t chunk_data[VD_AGENT_MAX_DATA_SIZE];
 
 /* Per chunk port data */
-struct vdagent_virtio_port_chunk_port_data port_data[VDP_LAST_PORT + 1];
+struct vdagent_virtio_port_chunk_port_data port_data[VDP_END_PORT];
 
 /* Writes are stored in a linked list of buffers, with both the header
+ data for a single message in 1 buffer. */
@@ -142,7 +141,7 @@ void vdagent_virtio_port_destroy(struct vdagent_virtio_port 
**vportp)
 wbuf = next_wbuf;
 }
 
-for (i = 0; i <= VDP_LAST_PORT; i++) {
+for (i = 0; i < VDP_END_PORT; i++) {
 free(vport->port_data[i].message_data);
 }
 
@@ -287,7 +286,7 @@ void vdagent_virtio_port_flush(struct vdagent_virtio_port 
**vportp)
 
 void vdagent_virtio_port_reset(struct vdagent_virtio_port *vport, int port)
 {
-if (port > VDP_LAST_PORT) {
+if (port >= VDP_END_PORT) {
 syslog(LOG_ERR, "vdagent_virtio_port_reset port out of range");
 return;
 }
@@ -427,7 +426,7 @@ static void vdagent_virtio_port_do_read(struct 
vdagent_virtio_port **vportp)
 vdagent_virtio_port_destroy(vportp);
 return;
 }
-if (vport->chunk_header.port > VDP_LAST_PORT) {
+if (vport->chunk_header.port >= VDP_END_PORT) {
 syslog(LOG_ERR, "chunk port %u out of range",
vport->chunk_header.port);
 vdagent_virtio_port_destroy(vportp);
-- 
2.6.2
___
Spice-devel mailing list
Spice-devel@lists.freedesktop.org
http://lists.freedesktop.org/mailman/listinfo/spice-devel


Re: [Spice-devel] [PATCH v2 1/3] vdagent: Group the client and server functions together

2015-11-13 Thread Francois Gouget
On Fri, 13 Nov 2015, Victor Toso wrote:
[...]
> PS: Now it seems to be correctly threaded in patchwork, thanks!
> https://patchwork.freedesktop.org/series/745/

Is there a reference to Spice's patchwork page somewhere?


-- 
Francois Gouget <fgou...@codeweavers.com>
___
Spice-devel mailing list
Spice-devel@lists.freedesktop.org
http://lists.freedesktop.org/mailman/listinfo/spice-devel


Re: [Spice-devel] [spice] server: Don't check the 'this' mjpeg_encoder pointer

2015-11-14 Thread Francois Gouget
On Fri, 13 Nov 2015, Frediano Ziglio wrote:
[...]
> >  void mjpeg_encoder_get_stats(MJpegEncoder *encoder, MJpegEncoderStats
> >  *stats)
> >  {
> > -spice_assert(encoder != NULL && stats != NULL);
> > +spice_assert(stats != NULL);
> >  stats->starting_bit_rate = encoder->starting_bit_rate;
> >  stats->cur_bit_rate = mjpeg_encoder_get_bit_rate(encoder);
> >  stats->avg_quality = (double)encoder->avg_quality / 
> > encoder->num_frames;
> > --
> > 2.6.2
> 
> Personally I think that these kind of checks are not helping that much and
> I would agree. A NULL pointer is a bug but removing the test cause a core
> on modern systems so adding it just slow down the execution and increase code
> size. For the same reason however even the check for stats could be removed
> like many other tests for NULL pointers.
> 
> It's quite question of style subject to personal opinions.

Yes, it's hard to know what to do when writing new code these days:
1) Follow surrounding code and thus use spice_assert(), in particular to 
   document the function's prerequisites.

2) Aknowledge that the server being a library it should not crash 
   the application (which I'm totally on board with, having had this 
   problem with libav), and use the spice_return_if_fail() instead of 
   spice_assert().

3) Still use spice_assert() but only for cases where the function would 
   have crashed anyway. I guess the advantage is that it makes the cause 
   of the crash clear without the need for debugging information in the 
   binary.

4) A mix of spice_assert() (point 3) for cases where Spice has no way 
   to return an error to the caller and would otherwise crash, and 
   spice_return_if_fail() (point 2) for other cases.

5) Consider all of this to drag down performance and use none of them.


For mjpeg_encoder_get_stats() specifically, I think in the end I would 
settle on either:

 * No check: the function is three lines long, it's painfully obvious 
   neither parameter should be NULL. Plus why single out the NULL 
   pointer case when a use after free is probably more likely?

 * Or a single spice_return_if_fail(stat != NULL) which may be more in 
   line with current policy (don't return statistics if not given a 
   place to put them).


-- 
Francois Gouget <fgou...@codeweavers.com>
___
Spice-devel mailing list
Spice-devel@lists.freedesktop.org
http://lists.freedesktop.org/mailman/listinfo/spice-devel


Re: [Spice-devel] [spice v3] server: Provide a framerate estimate based on the initial frames

2015-11-14 Thread Francois Gouget
On Fri, 13 Nov 2015, Frediano Ziglio wrote:
[...]
> > diff --git a/server/display-channel.h b/server/display-channel.h
> > index c3dcc29..24f9da5 100644
> > --- a/server/display-channel.h
> > +++ b/server/display-channel.h
> > @@ -152,6 +152,7 @@ struct Drawable {
> >  Ring glz_ring;
> >  
> >  red_time_t creation_time;
> > +red_time_t first_frame_time;
> >  int frames_count;
> >  int gradual_frames_count;
> >  int last_gradual_frame;
> 
> This here looks weird. ItemTrace should trace/record the frames and have a 
> first and count.
> I think however is more of a design problem than something related to your 
> patch.
> There are too many fields related to stream in Drawable.
[...]
> is not clear why the time keep updating with new frames.

The video stream detection code is pretty complex and undocumented (and 
buggy too). But my understanding is that a video stream is created only 
if at least twenty image 'blits' of the same size and type arrive, each 
within a maximum time interval from the previous one.

So the code was only keeping track of the current frame's creation time, 
and that of the previous one to check for the 'maximum time interval' 
condition. But basing a framerate estimate on just one frame interval 
would not be very precise. So to get a proper estimate I need to also 
keep track of the timestamp for the first frame in the series, so I can 
compute an average over the first 20 frames (which represents 0.67s at 
30fps so long enough to smooth over scheduling delays). Hence the need 
for the first_frame_time field.

Also the code does not keep the twenty frames in memory. My rough 
understanding and recollection of it is that as soon as it's done with a 
frame it frees it and only keeps the essential data into an ItemTrace 
structure. So to preserve the time of the first frame it's necessary to 
copy the first_frame_time field from frame to frame, and back and forth 
between ItemTrace and Drawable structures.


[...]
> > +/* Provide an fps estimate the video encoder can use when initializing
> > + * based on the frames that lead to the creation of the stream. Round 
> > to
> > + * the nearest integer, for instance 24 for 23.976.
> > + */
> > +uint64_t duration = drawable->creation_time -
> > drawable->first_frame_time;
> > +stream->input_fps = ((uint64_t)drawable->frames_count * 1000 * 1000 *
> > 1000 + duration / 2) / duration;
> 
> Just to be 100% sure I would check for duration == 0 and limit input_fps to
> MAX_FPS.

Sure. Will do.


> Which kind of test did you do?

Playing video with mplayer, totem and Flash (YouTube), with and without 
SpiceDeferredFPS and EnableSurfaces. The fps estimates were always 
within 1fps of the actual framerate.

-- 
Francois Gouget <fgou...@codeweavers.com>  
___
Spice-devel mailing list
Spice-devel@lists.freedesktop.org
http://lists.freedesktop.org/mailman/listinfo/spice-devel


Re: [Spice-devel] [spice] server: Don't check the 'this' mjpeg_encoder pointer

2015-11-16 Thread Francois Gouget
On Mon, 16 Nov 2015, Christophe Fergeau wrote:

> On Fri, Nov 13, 2015 at 04:14:17PM +0100, Francois Gouget wrote:
> > mjpeg_encoder_get_stats() was the only function to check it.
> 
> Could you trigger this assert in a somehow legit case? Or is this just
> for consistency?

It's for consistency and also as a way to figure out what to do for the 
GStreamer encoder without having to send the whole series for each 
iteration.

-- 
Francois Gouget <fgou...@codeweavers.com>
___
Spice-devel mailing list
Spice-devel@lists.freedesktop.org
http://lists.freedesktop.org/mailman/listinfo/spice-devel


[Spice-devel] [spice v4] server: Provide a framerate estimate based on the initial frames

2015-11-16 Thread Francois Gouget
This way the video encoder can actually count on a real estimate when
it is initializing.

Signed-off-by: Francois Gouget <fgou...@codeweavers.com>
---
 server/display-channel.h |  1 +
 server/red_worker.c  | 22 ++
 server/stream.h  |  1 +
 3 files changed, 20 insertions(+), 4 deletions(-)

Check that duration is not 0 and that we don't exceed MAX_FPS.

diff --git a/server/display-channel.h b/server/display-channel.h
index a9ae40a..23d7a05 100644
--- a/server/display-channel.h
+++ b/server/display-channel.h
@@ -152,6 +152,7 @@ struct Drawable {
 Ring glz_ring;
 
 red_time_t creation_time;
+red_time_t first_frame_time;
 int frames_count;
 int gradual_frames_count;
 int last_gradual_frame;
diff --git a/server/red_worker.c b/server/red_worker.c
index 165e4c0..23834d3 100644
--- a/server/red_worker.c
+++ b/server/red_worker.c
@@ -984,6 +984,7 @@ static void 
display_stream_trace_add_drawable(DisplayChannel *display, Drawable
 
 trace = >items_trace[display->next_item_trace++ & 
ITEMS_TRACE_MASK];
 trace->time = item->creation_time;
+trace->first_frame_time = item->first_frame_time;
 trace->frames_count = item->frames_count;
 trace->gradual_frames_count = item->gradual_frames_count;
 trace->last_gradual_frame = item->last_gradual_frame;
@@ -1772,7 +1773,16 @@ static void display_channel_create_stream(DisplayChannel 
*display, Drawable *dra
 SpiceBitmap *bitmap = >red_drawable->u.copy.src_bitmap->u.bitmap;
 stream->top_down = !!(bitmap->flags & SPICE_BITMAP_FLAGS_TOP_DOWN);
 drawable->stream = stream;
-stream->input_fps = MAX_FPS;
+/* Provide an fps estimate the video encoder can use when initializing
+ * based on the frames that lead to the creation of the stream. Round to
+ * the nearest integer, for instance 24 for 23.976.
+ */
+uint64_t duration = drawable->creation_time - drawable->first_frame_time;
+if (duration > (uint64_t)drawable->frames_count * 1000 * 1000 * 1000 / 
MAX_FPS) {
+stream->input_fps = ((uint64_t)drawable->frames_count * 1000 * 1000 * 
1000 + duration / 2) / duration;
+} else {
+stream->input_fps = MAX_FPS;
+}
 stream->num_input_frames = 0;
 stream->input_fps_start_time = drawable->creation_time;
 display->streams_size_total += stream->width * stream->height;
@@ -1780,10 +1790,10 @@ static void 
display_channel_create_stream(DisplayChannel *display, Drawable *dra
 FOREACH_DCC(display, dcc_ring_item, next, dcc) {
 dcc_create_stream(dcc, stream);
 }
-spice_debug("stream %d %dx%d (%d, %d) (%d, %d)",
+spice_debug("stream %d %dx%d (%d, %d) (%d, %d) %u fps",
 (int)(stream - display->streams_buf), stream->width,
 stream->height, stream->dest_area.left, stream->dest_area.top,
-stream->dest_area.right, stream->dest_area.bottom);
+stream->dest_area.right, stream->dest_area.bottom, 
stream->input_fps);
 return;
 }
 
@@ -2009,11 +2019,13 @@ static int is_stream_start(Drawable *drawable)
 // returns whether a stream was created
 static int display_channel_stream_add_frame(DisplayChannel *display,
 Drawable *frame_drawable,
+red_time_t first_frame_time,
 int frames_count,
 int gradual_frames_count,
 int last_gradual_frame)
 {
 update_copy_graduality(display, frame_drawable);
+frame_drawable->first_frame_time = first_frame_time;
 frame_drawable->frames_count = frames_count + 1;
 frame_drawable->gradual_frames_count  = gradual_frames_count;
 
@@ -2074,6 +2086,7 @@ static void 
display_channel_stream_maintenance(DisplayChannel *display,
  FALSE);
 if (is_next_frame != STREAM_FRAME_NONE) {
 display_channel_stream_add_frame(display, candidate,
+ prev->first_frame_time,
  prev->frames_count,
  prev->gradual_frames_count,
  prev->last_gradual_frame);
@@ -2235,6 +2248,7 @@ static void red_use_stream_trace(DisplayChannel *display, 
Drawable *drawable)
>dest_area, trace->time, NULL, 
FALSE) !=
STREAM_FRAME_NONE) {
 if (display_channel_stream_add_frame(display, drawable,
+ trace->first_frame_time,
  trace->frames_count,
 

[Spice-devel] server: Include stdint.h for int64_t

2015-11-15 Thread Francois Gouget
This fixes a compilation error with gcc 4.4 on RHEL 6.

Signed-off-by: Francois Gouget <fgou...@codeweavers.com>
---
 server/utils.h | 1 +
 1 file changed, 1 insertion(+)

diff --git a/server/utils.h b/server/utils.h
index 1ebc32f..cae03d4 100644
--- a/server/utils.h
+++ b/server/utils.h
@@ -19,6 +19,7 @@
 # define UTILS_H_
 
 #include 
+#include 
 
 typedef int64_t red_time_t;
 
-- 
2.6.2

___
Spice-devel mailing list
Spice-devel@lists.freedesktop.org
http://lists.freedesktop.org/mailman/listinfo/spice-devel


[Spice-devel] server: Duplicate typedef definitions are not allowed in C99

2015-11-15 Thread Francois Gouget
This fixes some compilation errors with gcc 4.4.7 on RHEL 6.

Signed-off-by: Francois Gouget <fgou...@codeweavers.com>
---
 server/red_channel.h| 1 -
 server/red_dispatcher.h | 1 -
 server/red_worker.c | 4 ++--
 3 files changed, 2 insertions(+), 4 deletions(-)

diff --git a/server/red_channel.h b/server/red_channel.h
index eda4436..4deecb6 100644
--- a/server/red_channel.h
+++ b/server/red_channel.h
@@ -128,7 +128,6 @@ typedef struct OutgoingHandler {
 
 /* Red Channel interface */
 
-typedef struct RedsStream RedsStream;
 typedef struct RedChannel RedChannel;
 typedef struct RedChannelClient RedChannelClient;
 typedef struct RedClient RedClient;
diff --git a/server/red_dispatcher.h b/server/red_dispatcher.h
index 02337b8..fef067c 100644
--- a/server/red_dispatcher.h
+++ b/server/red_dispatcher.h
@@ -23,7 +23,6 @@
 #include "red_channel.h"
 
 typedef struct RedDispatcher RedDispatcher;
-typedef struct RedChannelClient RedChannelClient;
 
 typedef struct AsyncCommand AsyncCommand;
 
diff --git a/server/red_worker.c b/server/red_worker.c
index 9673288..165e4c0 100644
--- a/server/red_worker.c
+++ b/server/red_worker.c
@@ -233,7 +233,7 @@ typedef struct RedSurface {
 QXLReleaseInfoExt create, destroy;
 } RedSurface;
 
-typedef struct RedWorker {
+struct RedWorker {
 pthread_t thread;
 clockid_t clockid;
 QXLInstance *qxl;
@@ -290,7 +290,7 @@ typedef struct RedWorker {
 int driver_cap_monitors_config;
 
 FILE *record_fd;
-} RedWorker;
+};
 
 typedef enum {
 BITMAP_DATA_TYPE_INVALID,
-- 
2.6.2
___
Spice-devel mailing list
Spice-devel@lists.freedesktop.org
http://lists.freedesktop.org/mailman/listinfo/spice-devel


  1   2   3   4   5   6   7   8   9   >