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

Submitted by Francois Gouget on June 10, 2015, 3:38 p.m.

Details

Message ID alpine.DEB.2.20.1506101106190.23792@amboise
State New
Headers show

Not browsing as part of any series.

Commit Message

Francois Gouget June 10, 2015, 3:38 p.m.
Signed-off-by: Francois Gouget <fgouget@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(-)

Patch hide | download patch | download mbox

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)						\
+	$(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 e7c9a56..97e6e13 100644
--- a/server/gstreamer_encoder.c
+++ b/server/gstreamer_encoder.c
@@ -152,7 +152,13 @@  static void adjust_bit_rate(GstEncoder *encoder)
 
 static gboolean set_appsrc_caps(GstEncoder *encoder)
 {
-    GstCaps *new_caps = gst_caps_new_simple("video/x-raw-rgb",
+    GstCaps *new_caps = gst_caps_new_simple(
+#ifdef HAVE_GSTREAMER_0_10
+        "video/x-raw-rgb",
+#else
+        "video/x-raw",
+        "format", G_TYPE_STRING, "BGRx",
+#endif
         "bpp", G_TYPE_INT, encoder->format->bpp,
         "depth", G_TYPE_INT, encoder->format->depth,
         "width", G_TYPE_INT, encoder->width,
@@ -183,8 +189,12 @@  static gboolean construct_pipeline(GstEncoder *encoder, const SpiceBitmap *bitma
     switch (encoder->base.codec_type)
     {
     case SPICE_VIDEO_CODEC_TYPE_MJPEG:
+#ifdef HAVE_GSTREAMER_0_10
         gstenc_name = "ffenc_mjpeg";
         no_clock = TRUE;
+#else
+        gstenc_name = "avenc_mjpeg";
+#endif
         break;
     case SPICE_VIDEO_CODEC_TYPE_VP8:
         gstenc_name = "vp8enc";
@@ -193,9 +203,14 @@  static gboolean construct_pipeline(GstEncoder *encoder, const SpiceBitmap *bitma
         spice_warning("unsupported codec type %d", encoder->base.codec_type);
         return FALSE;
     }
+#ifdef HAVE_GSTREAMER_0_10
+    const gchar *converter = "ffmpegcolorspace";
+#else
+    const gchar *converter = "videoconvert";
+#endif
 
     GError *err = NULL;
-    gchar *desc = g_strdup_printf("appsrc name=src format=2 do-timestamp=true ! ffmpegcolorspace ! %s name=encoder ! appsink name=sink", gstenc_name);
+    gchar *desc = g_strdup_printf("appsrc name=src format=2 do-timestamp=true ! %s ! %s name=encoder ! appsink name=sink", converter, 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);
@@ -210,16 +225,34 @@  static gboolean construct_pipeline(GstEncoder *encoder, const SpiceBitmap *bitma
 
     /* 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) {
+    switch (encoder->base.codec_type) {
+    case SPICE_VIDEO_CODEC_TYPE_MJPEG:
+        g_object_set(G_OBJECT(encoder->gstenc),
+                     "bitrate", encoder->bit_rate,
+                     NULL);
+        break;
+    case SPICE_VIDEO_CODEC_TYPE_VP8:
         /* See http://www.webmproject.org/docs/encoder-parameters/ */
         g_object_set(G_OBJECT(encoder->gstenc),
+#ifdef HAVE_GSTREAMER_0_10
                      "mode", 1, /* CBR */
+                     "bitrate", encoder->bit_rate,
                      "max-latency", 0,
                      "speed", 7,
+#else
+                     "end-usage", 1, /* CBR */
+                     "target-bitrate", encoder->bit_rate,
+                     "lag-in-frames", 0,
+                     "deadline", GST_SECOND / get_source_fps(encoder) / 2,
+#endif
                      "resize-allowed", TRUE,
                      "threads", g_get_num_processors() - 1,
                      NULL);
+        break;
+    default:
+        spice_warning("unknown encoder type %d", encoder->base.codec_type);
+        reset_pipeline(encoder);
+        return FALSE;
     }
 
     /* Set the source caps */
@@ -263,7 +296,14 @@  static int push_raw_frame(GstEncoder *encoder, const SpiceBitmap *bitmap,
     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);
-    uint8_t *dst = GST_BUFFER_DATA(buffer);
+#ifdef HAVE_GSTREAMER_0_10
+    uint8_t *b = GST_BUFFER_DATA(buffer);
+#else
+    GstMapInfo map;
+    gst_buffer_map(buffer, &map, GST_MAP_WRITE);
+    uint8_t *b = map.data;
+#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.
@@ -322,10 +362,13 @@  static int push_raw_frame(GstEncoder *encoder, const SpiceBitmap *bitmap,
             dst += stream_stride;
             chunk_offset += bitmap->stride;
         }
-        spice_assert(dst - GST_BUFFER_DATA(buffer) == len);
+        spice_assert(dst - b == len);
     }
-
+#ifdef HAVE_GSTREAMER_0_10
     gst_buffer_set_caps(buffer, encoder->src_caps);
+#else
+    gst_buffer_unmap(buffer, &map);
+#endif
     GST_BUFFER_OFFSET(buffer) = encoder->frame++;
 
     GstFlowReturn ret = gst_app_src_push_buffer(encoder->appsrc, buffer);
@@ -341,17 +384,33 @@  static int pull_compressed_buffer(GstEncoder *encoder,
                                   uint8_t **outbuf, size_t *outbuf_size,
                                   int *data_size)
 {
-    GstBuffer *buffer = gst_app_sink_pull_buffer(encoder->appsink);
+    GstBuffer *buffer;
+
+#ifdef HAVE_GSTREAMER_0_10
+    buffer = gst_app_sink_pull_buffer(encoder->appsink);
+#else
+    GstSample *sample = gst_app_sink_pull_sample(encoder->appsink);
+    buffer = gst_sample_get_buffer(sample);
+#endif
     if (buffer) {
+#ifdef HAVE_GSTREAMER_0_10
         int len = GST_BUFFER_SIZE(buffer);
+#else
+        int len = gst_buffer_get_size(buffer);
+#endif
         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), len);
+#ifdef HAVE_GSTREAMER_0_10
+        memcpy(*outbuf,  GST_BUFFER_DATA(buffer), len);
         gst_buffer_unref(buffer);
+#else
+        gst_buffer_extract(buffer, 0, *outbuf, len);
+        gst_sample_unref(sample);
+#endif
         *data_size = len;
         return VIDEO_ENCODER_FRAME_ENCODE_DONE;
     }
diff --git a/server/red_dispatcher.c b/server/red_dispatcher.c
index 4330f2e..08623e2 100644
--- a/server/red_dispatcher.c
+++ b/server/red_dispatcher.c
@@ -257,7 +257,7 @@  static const EnumNames video_encoder_names[] = {
 
 static create_video_encoder_proc video_encoder_procs[] = {
     &create_mjpeg_encoder,
-#ifdef HAVE_GSTREAMER_0_10
+#if defined(HAVE_GSTREAMER_0_10) || defined(HAVE_GSTREAMER_1_0)
     &create_gstreamer_encoder,
 #else
     NULL,

Comments

Il 10/06/2015 17:38, Francois Gouget ha scritto:
> Signed-off-by: Francois Gouget <fgouget@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

Probably another change in configure is needed to avoid this:
> /bin/bash ../../libtool  --tag=CC   --mode=link gcc -std=gnu99  -g -O2
> -fstack-protector --param=ssp-buffer-size=4 -Wformat
> -Werror=format-security  -Wl,-z,relro -lm -o test_display_no_ssl
> basic_event_loop.o  test_display_base.o test_display_no_ssl.o 
> ../../spice-common/common/libspice-common.la
> ../../server/libspice-server.la -lglib-2.0    
> libtool: link: gcc -std=gnu99 -g -O2 -fstack-protector
> --param=ssp-buffer-size=4 -Wformat -Werror=format-security -Wl,-z
> -Wl,relro -o .libs/test_display_no_ssl basic_event_loop.o
> test_display_base.o test_display_no_ssl.o 
> ../../spice-common/common/.libs/libspice-common.a -lm -lpixman-1
> -lopus ../../server/.libs/libspice-server.so -lglib-2.0 -pthread
> ../../server/.libs/libspice-server.so: undefined reference to
> `g_get_num_processors'

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

>
>
>  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)						\
> +	$(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 e7c9a56..97e6e13 100644
> --- a/server/gstreamer_encoder.c
> +++ b/server/gstreamer_encoder.c
> @@ -152,7 +152,13 @@ static void adjust_bit_rate(GstEncoder *encoder)
>  
>  static gboolean set_appsrc_caps(GstEncoder *encoder)
>  {
> -    GstCaps *new_caps = gst_caps_new_simple("video/x-raw-rgb",
> +    GstCaps *new_caps = gst_caps_new_simple(
> +#ifdef HAVE_GSTREAMER_0_10
> +        "video/x-raw-rgb",
> +#else
> +        "video/x-raw",
> +        "format", G_TYPE_STRING, "BGRx",
> +#endif
>          "bpp", G_TYPE_INT, encoder->format->bpp,
>          "depth", G_TYPE_INT, encoder->format->depth,
>          "width", G_TYPE_INT, encoder->width,
> @@ -183,8 +189,12 @@ static gboolean construct_pipeline(GstEncoder *encoder, const SpiceBitmap *bitma
>      switch (encoder->base.codec_type)
>      {
>      case SPICE_VIDEO_CODEC_TYPE_MJPEG:
> +#ifdef HAVE_GSTREAMER_0_10
>          gstenc_name = "ffenc_mjpeg";
>          no_clock = TRUE;
> +#else
> +        gstenc_name = "avenc_mjpeg";
> +#endif
>          break;
>      case SPICE_VIDEO_CODEC_TYPE_VP8:
>          gstenc_name = "vp8enc";
> @@ -193,9 +203,14 @@ static gboolean construct_pipeline(GstEncoder *encoder, const SpiceBitmap *bitma
>          spice_warning("unsupported codec type %d", encoder->base.codec_type);
>          return FALSE;
>      }
> +#ifdef HAVE_GSTREAMER_0_10
> +    const gchar *converter = "ffmpegcolorspace";
> +#else
> +    const gchar *converter = "videoconvert";
> +#endif
>  
>      GError *err = NULL;
> -    gchar *desc = g_strdup_printf("appsrc name=src format=2 do-timestamp=true ! ffmpegcolorspace ! %s name=encoder ! appsink name=sink", gstenc_name);
> +    gchar *desc = g_strdup_printf("appsrc name=src format=2 do-timestamp=true ! %s ! %s name=encoder ! appsink name=sink", converter, 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);
> @@ -210,16 +225,34 @@ static gboolean construct_pipeline(GstEncoder *encoder, const SpiceBitmap *bitma
>  
>      /* 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) {
> +    switch (encoder->base.codec_type) {
> +    case SPICE_VIDEO_CODEC_TYPE_MJPEG:
> +        g_object_set(G_OBJECT(encoder->gstenc),
> +                     "bitrate", encoder->bit_rate,
> +                     NULL);
> +        break;
> +    case SPICE_VIDEO_CODEC_TYPE_VP8:
>          /* See http://www.webmproject.org/docs/encoder-parameters/ */
>          g_object_set(G_OBJECT(encoder->gstenc),
> +#ifdef HAVE_GSTREAMER_0_10
>                       "mode", 1, /* CBR */
> +                     "bitrate", encoder->bit_rate,
>                       "max-latency", 0,
>                       "speed", 7,
> +#else
> +                     "end-usage", 1, /* CBR */
> +                     "target-bitrate", encoder->bit_rate,
> +                     "lag-in-frames", 0,
> +                     "deadline", GST_SECOND / get_source_fps(encoder) / 2,
> +#endif
>                       "resize-allowed", TRUE,
>                       "threads", g_get_num_processors() - 1,
>                       NULL);
> +        break;
> +    default:
> +        spice_warning("unknown encoder type %d", encoder->base.codec_type);
> +        reset_pipeline(encoder);
> +        return FALSE;
>      }
>  
>      /* Set the source caps */
> @@ -263,7 +296,14 @@ static int push_raw_frame(GstEncoder *encoder, const SpiceBitmap *bitmap,
>      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);
> -    uint8_t *dst = GST_BUFFER_DATA(buffer);
> +#ifdef HAVE_GSTREAMER_0_10
> +    uint8_t *b = GST_BUFFER_DATA(buffer);
> +#else
> +    GstMapInfo map;
> +    gst_buffer_map(buffer, &map, GST_MAP_WRITE);
> +    uint8_t *b = map.data;
> +#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.
> @@ -322,10 +362,13 @@ static int push_raw_frame(GstEncoder *encoder, const SpiceBitmap *bitmap,
>              dst += stream_stride;
>              chunk_offset += bitmap->stride;
>          }
> -        spice_assert(dst - GST_BUFFER_DATA(buffer) == len);
> +        spice_assert(dst - b == len);
>      }
> -
> +#ifdef HAVE_GSTREAMER_0_10
>      gst_buffer_set_caps(buffer, encoder->src_caps);
> +#else
> +    gst_buffer_unmap(buffer, &map);
> +#endif
>      GST_BUFFER_OFFSET(buffer) = encoder->frame++;
>  
>      GstFlowReturn ret = gst_app_src_push_buffer(encoder->appsrc, buffer);
> @@ -341,17 +384,33 @@ static int pull_compressed_buffer(GstEncoder *encoder,
>                                    uint8_t **outbuf, size_t *outbuf_size,
>                                    int *data_size)
>  {
> -    GstBuffer *buffer = gst_app_sink_pull_buffer(encoder->appsink);
> +    GstBuffer *buffer;
> +
> +#ifdef HAVE_GSTREAMER_0_10
> +    buffer = gst_app_sink_pull_buffer(encoder->appsink);
> +#else
> +    GstSample *sample = gst_app_sink_pull_sample(encoder->appsink);
> +    buffer = gst_sample_get_buffer(sample);
> +#endif
>      if (buffer) {
> +#ifdef HAVE_GSTREAMER_0_10
>          int len = GST_BUFFER_SIZE(buffer);
> +#else
> +        int len = gst_buffer_get_size(buffer);
> +#endif
>          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), len);
> +#ifdef HAVE_GSTREAMER_0_10
> +        memcpy(*outbuf,  GST_BUFFER_DATA(buffer), len);
>          gst_buffer_unref(buffer);
> +#else
> +        gst_buffer_extract(buffer, 0, *outbuf, len);
> +        gst_sample_unref(sample);
> +#endif
>          *data_size = len;
>          return VIDEO_ENCODER_FRAME_ENCODE_DONE;
>      }
> diff --git a/server/red_dispatcher.c b/server/red_dispatcher.c
> index 4330f2e..08623e2 100644
> --- a/server/red_dispatcher.c
> +++ b/server/red_dispatcher.c
> @@ -257,7 +257,7 @@ static const EnumNames video_encoder_names[] = {
>  
>  static create_video_encoder_proc video_encoder_procs[] = {
>      &create_mjpeg_encoder,
> -#ifdef HAVE_GSTREAMER_0_10
> +#if defined(HAVE_GSTREAMER_0_10) || defined(HAVE_GSTREAMER_1_0)
>      &create_gstreamer_encoder,
>  #else
>      NULL,