[Spice-devel,v6,19/26] server: Add support for GStreamer 0.10

Submitted by Francois Gouget on Oct. 14, 2015, 3:33 p.m.

Details

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

Not browsing as part of any series.

Commit Message

Francois Gouget Oct. 14, 2015, 3:33 p.m.
configure will use GStreamer 1.0 if present and fall back to
GStreamer 0.10 otherwise.

Signed-off-by: Francois Gouget <fgouget@codeweavers.com>
---
 configure.ac               | 35 ++++++++++++++++----
 server/Makefile.am         |  8 +++++
 server/gstreamer_encoder.c | 79 ++++++++++++++++++++++++++++++++++++++++++----
 server/red_dispatcher.c    |  2 +-
 server/video_encoder.h     |  2 +-
 5 files changed, 112 insertions(+), 14 deletions(-)

Patch hide | download patch | download mbox

diff --git a/configure.ac b/configure.ac
index 3c1882f..eca8295 100644
--- a/configure.ac
+++ b/configure.ac
@@ -82,14 +82,14 @@  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 1.0 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="yes"
+                      [enable_gstreamer="1.0"
                        have_gstreamer_1_0="yes"],
                       [have_gstreamer_1_0="no"])
     if test "x$have_gstreamer_1_0" = "xyes"; then
@@ -97,7 +97,7 @@  if test "x$enable_gstreamer" != "xno"; then
         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" = "xyes"; then
+    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
@@ -105,6 +105,29 @@  else
 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="0.10"
+                       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" = "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
+    have_gstreamer_0_10="no"
+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"])
@@ -334,7 +357,7 @@  echo "
 
         Smartcard:                ${have_smartcard}
 
-        GStreamer 1.0:            ${have_gstreamer_1_0}
+        GStreamer:                ${enable_gstreamer}
 
         SASL support:             ${enable_sasl}
 
diff --git a/server/Makefile.am b/server/Makefile.am
index 60c2036..0fa8d19 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)		\
 	$(GSTREAMER_1_0_CFLAGS)			\
 	$(SPICE_PROTOCOL_CFLAGS)		\
 	$(SSL_CFLAGS)				\
@@ -43,6 +44,7 @@  libspice_server_la_LIBADD =						\
 	$(PIXMAN_LIBS)							\
 	$(SASL_LIBS)							\
 	$(SLIRP_LIBS)							\
+	$(GSTREAMER_0_10_LIBS)						\
 	$(GSTREAMER_1_0_LIBS)						\
 	$(SSL_LIBS)							\
 	$(Z_LIBS)							\
@@ -146,6 +148,12 @@  libspice_server_la_SOURCES +=	\
 	$(NULL)
 endif
 
+if SUPPORT_GSTREAMER_0_10
+libspice_server_la_SOURCES +=	\
+	gstreamer_encoder.c			\
+	$(NULL)
+endif
+
 if SUPPORT_GSTREAMER_1_0
 libspice_server_la_SOURCES +=	\
 	gstreamer_encoder.c			\
diff --git a/server/gstreamer_encoder.c b/server/gstreamer_encoder.c
index 82f6aee..8694f23 100644
--- a/server/gstreamer_encoder.c
+++ b/server/gstreamer_encoder.c
@@ -32,7 +32,9 @@ 
 
 #define GSTE_DEFAULT_FPS 30
 
-#define DO_ZERO_COPY
+#ifndef HAVE_GSTREAMER_0_10
+# define DO_ZERO_COPY
+#endif
 
 #define NANO_SECOND (1000000000LL)
 #define MILLI_SECOND (1000LL)
@@ -42,12 +44,19 @@  typedef struct {
     SpiceBitmapFmt spice_format;
     const char *format;
     uint32_t bpp;
+    uint32_t depth;
+    uint32_t endianness;
+    uint32_t blue_mask;
+    uint32_t green_mask;
+    uint32_t red_mask;
 } SpiceFormatForGStreamer;
 
 typedef struct SpiceGstVideoBuffer {
     VideoBuffer base;
     GstBuffer *gst_buffer;
+#ifndef HAVE_GSTREAMER_0_10
     GstMapInfo map;
+#endif
 } SpiceGstVideoBuffer;
 
 typedef struct {
@@ -265,6 +274,9 @@  typedef struct SpiceGstEncoder {
 static void gst_video_buffer_free(VideoBuffer *video_buffer)
 {
     SpiceGstVideoBuffer *buffer = (SpiceGstVideoBuffer*)video_buffer;
+#ifndef HAVE_GSTREAMER_0_10
+        gst_buffer_unmap(buffer->gst_buffer, &buffer->map);
+#endif
     gst_buffer_unref(buffer->gst_buffer);
     free(buffer);
 }
@@ -694,11 +706,11 @@  static SpiceFormatForGStreamer *map_format(SpiceBitmapFmt format)
      * section-types-definitions.html documents.
      */
     static SpiceFormatForGStreamer format_map[] =  {
-        {SPICE_BITMAP_FMT_RGBA, "BGRA", 32},
+        {SPICE_BITMAP_FMT_RGBA, "BGRA", 32, 24, 4321, 0xff000000, 0xff0000, 0xff00},
         /* TODO: Test the other formats */
-        {SPICE_BITMAP_FMT_32BIT, "BGRx", 32},
-        {SPICE_BITMAP_FMT_24BIT, "BGR", 24},
-        {SPICE_BITMAP_FMT_16BIT, "BGR15", 16},
+        {SPICE_BITMAP_FMT_32BIT, "BGRx", 32, 24, 4321, 0xff000000, 0xff0000, 0xff00},
+        {SPICE_BITMAP_FMT_24BIT, "BGR", 24, 24, 4321, 0xff0000, 0xff00, 0xff},
+        {SPICE_BITMAP_FMT_16BIT, "BGR15", 16, 15, 4321, 0x001f, 0x03E0, 0x7C00},
     };
 
     int i;
@@ -717,8 +729,18 @@  static void set_appsrc_caps(SpiceGstEncoder *encoder)
         gst_caps_unref(encoder->src_caps);
     }
     encoder->src_caps = gst_caps_new_simple(
+#ifdef HAVE_GSTREAMER_0_10
+        "video/x-raw-rgb",
+        "bpp", G_TYPE_INT, encoder->format->bpp,
+        "depth", G_TYPE_INT, encoder->format->depth,
+        "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,
+#else
         "video/x-raw",
         "format", G_TYPE_STRING, encoder->format->format,
+#endif
         "width", G_TYPE_INT, encoder->width,
         "height", G_TYPE_INT, encoder->height,
         "framerate", GST_TYPE_FRACTION, get_source_fps(encoder), 1,
@@ -731,7 +753,11 @@  static const gchar* get_gst_codec_name(SpiceGstEncoder *encoder)
     switch (encoder->base.codec_type)
     {
     case SPICE_VIDEO_CODEC_TYPE_MJPEG:
+#ifdef HAVE_GSTREAMER_0_10
+        return "ffenc_mjpeg";
+#else
         return "avenc_mjpeg";
+#endif
     case SPICE_VIDEO_CODEC_TYPE_VP8:
         return "vp8enc";
     case SPICE_VIDEO_CODEC_TYPE_H264:
@@ -809,9 +835,14 @@  static gboolean construct_pipeline(SpiceGstEncoder *encoder, const SpiceBitmap *
     if (!gstenc_name) {
         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 ! videoconvert ! %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);
@@ -846,10 +877,17 @@  static gboolean construct_pipeline(SpiceGstEncoder *encoder, const SpiceBitmap *
         g_object_set(G_OBJECT(encoder->gstenc),
                      "resize-allowed", TRUE, /* for very low bit rates */
                      "min-quantizer", 10, /* seems virtually lossless */
+#ifdef HAVE_GSTREAMER_0_10
+                     "mode", 1, /* CBR */
+                     "max-latency", 0, /* zero-frame latency */
+                     "error-resilient", TRUE, /* for client frame drops */
+                     "speed", 7, /* ultrafast */
+#else
                      "end-usage", 1, /* CBR */
                      "lag-in-frames", 0, /* zero-frame latency */
                      "error-resilient", 1, /* for client frame drops */
                      "deadline", 1000000 / get_source_fps(encoder) / 2, /* usec */
+#endif
                      "threads", core_count - 1,
                      NULL);
         break;
@@ -1025,9 +1063,14 @@  static int push_raw_frame(SpiceGstEncoder *encoder, const SpiceBitmap *bitmap,
     const uint32_t height = src->bottom - src->top;
     const uint32_t stream_stride = (src->right - src->left) * encoder->format->bpp / 8;
     uint32_t len = stream_stride * height;
+#ifdef HAVE_GSTREAMER_0_10
+    GstBuffer *buffer = gst_buffer_new_and_alloc(len);
+    uint8_t *dst = GST_BUFFER_DATA(buffer);
+#else
     GstBuffer *buffer = gst_buffer_new();
     /* TODO Use GST_MAP_INFO_INIT once GStreamer 1.4.5 is no longer relevant */
     GstMapInfo map = { .memory = NULL };
+#endif
 
     /* 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.
@@ -1039,6 +1082,7 @@  static int push_raw_frame(SpiceGstEncoder *encoder, const SpiceBitmap *bitmap,
         /* We have to do a line-by-line copy because for each we have to leave
          * out pixels on the left or right.
          */
+#ifndef HAVE_GSTREAMER_0_10
         GstMemory *mem = gst_allocator_alloc(NULL, len, NULL);
         if (!mem) {
             gst_buffer_unref(buffer);
@@ -1046,11 +1090,14 @@  static int push_raw_frame(SpiceGstEncoder *encoder, const SpiceBitmap *bitmap,
         }
         spice_assert(gst_memory_map(mem, &map, GST_MAP_WRITE));
         uint8_t *dst = map.data;
+#endif
 
         chunk_offset += src->left * encoder->format->bpp / 8;
         if (!line_copy(encoder, bitmap, chunk_offset, stream_stride, height, dst)) {
+#ifndef HAVE_GSTREAMER_0_10
             gst_memory_unmap(map.memory, &map);
             gst_memory_unref(map.memory);
+#endif
             gst_buffer_unref(buffer);
             return VIDEO_ENCODER_FRAME_UNSUPPORTED;
         }
@@ -1070,6 +1117,7 @@  static int push_raw_frame(SpiceGstEncoder *encoder, const SpiceBitmap *bitmap,
          */
 #endif
 
+#ifndef HAVE_GSTREAMER_0_10
         if (len) {
             GstMemory *mem = gst_allocator_alloc(NULL, len, NULL);
             if (!mem) {
@@ -1079,12 +1127,15 @@  static int push_raw_frame(SpiceGstEncoder *encoder, const SpiceBitmap *bitmap,
             spice_assert(gst_memory_map(mem, &map, GST_MAP_WRITE));
         }
         uint8_t *dst = map.data;
+#endif
 
         while (len && chunk_index < chunks->num_chunks) {
             /* Make sure that the chunk is not padded */
             if (chunks->chunk[chunk_index].len % bitmap->stride != 0) {
+#ifndef HAVE_GSTREAMER_0_10
                 gst_memory_unmap(map.memory, &map);
                 gst_memory_unref(map.memory);
+#endif
                 gst_buffer_unref(buffer);
                 spice_warning("chunk %d/%d is padded, cannot copy it",
                               chunk_index, chunks->num_chunks);
@@ -1106,10 +1157,14 @@  static int push_raw_frame(SpiceGstEncoder *encoder, const SpiceBitmap *bitmap,
         }
         spice_assert(len == 0);
     }
+#ifdef HAVE_GSTREAMER_0_10
+    gst_buffer_set_caps(buffer, encoder->src_caps);
+#else
     if (map.memory) {
         gst_memory_unmap(map.memory, &map);
         gst_buffer_append_memory(buffer, map.memory);
     }
+#endif
     GST_BUFFER_OFFSET(buffer) = encoder->frame++;
 
     GstFlowReturn ret = gst_app_src_push_buffer(encoder->appsrc, buffer);
@@ -1125,6 +1180,17 @@  static int push_raw_frame(SpiceGstEncoder *encoder, const SpiceBitmap *bitmap,
 static int pull_compressed_buffer(SpiceGstEncoder *encoder,
                                   VideoBuffer **video_buffer)
 {
+#ifdef HAVE_GSTREAMER_0_10
+    SpiceGstVideoBuffer *buffer = create_gst_video_buffer();
+    buffer->gst_buffer = gst_app_sink_pull_buffer(encoder->appsink);
+    if (buffer->gst_buffer) {
+        buffer->base.data = GST_BUFFER_DATA(buffer->gst_buffer);
+        buffer->base.size = GST_BUFFER_SIZE(buffer->gst_buffer);
+        *video_buffer = (VideoBuffer*)buffer;
+        return VIDEO_ENCODER_FRAME_ENCODE_DONE;
+    }
+    buffer->base.free((VideoBuffer*)buffer);
+#else
     GstSample *sample = gst_app_sink_pull_sample(encoder->appsink);
     if (sample) {
         SpiceGstVideoBuffer *buffer = create_gst_video_buffer();
@@ -1141,6 +1207,7 @@  static int pull_compressed_buffer(SpiceGstEncoder *encoder,
         buffer->base.free((VideoBuffer*)buffer);
         gst_sample_unref(sample);
     }
+#endif
     spice_debug("failed to pull the compressed buffer");
     return VIDEO_ENCODER_FRAME_UNSUPPORTED;
 }
diff --git a/server/red_dispatcher.c b/server/red_dispatcher.c
index 60eef24..1ada928 100644
--- a/server/red_dispatcher.c
+++ b/server/red_dispatcher.c
@@ -258,7 +258,7 @@  static const EnumNames video_encoder_names[] = {
 
 static new_video_encoder_t video_encoder_procs[] = {
     &mjpeg_encoder_new,
-#ifdef HAVE_GSTREAMER_1_0
+#if defined(HAVE_GSTREAMER_1_0) || defined(HAVE_GSTREAMER_0_10)
     &gstreamer_encoder_new,
 #else
     NULL,
diff --git a/server/video_encoder.h b/server/video_encoder.h
index 0214893..c497e88 100644
--- a/server/video_encoder.h
+++ b/server/video_encoder.h
@@ -180,7 +180,7 @@  VideoEncoder* mjpeg_encoder_new(SpiceVideoCodecType codec_type,
                                 uint64_t starting_bit_rate,
                                 VideoEncoderRateControlCbs *cbs,
                                 void *cbs_opaque);
-#ifdef HAVE_GSTREAMER_1_0
+#if defined(HAVE_GSTREAMER_1_0) || defined(HAVE_GSTREAMER_0_10)
 VideoEncoder* gstreamer_encoder_new(SpiceVideoCodecType codec_type,
                                     uint64_t starting_bit_rate,
                                     VideoEncoderRateControlCbs *cbs,

Comments

Ah, now I see it's this patch which needs to disable zero copy. ACK.

On Wed, Oct 14, 2015 at 05:33:26PM +0200, Francois Gouget wrote:
> configure will use GStreamer 1.0 if present and fall back to
> GStreamer 0.10 otherwise.
> 
> Signed-off-by: Francois Gouget <fgouget@codeweavers.com>
> ---
>  configure.ac               | 35 ++++++++++++++++----
>  server/Makefile.am         |  8 +++++
>  server/gstreamer_encoder.c | 79 ++++++++++++++++++++++++++++++++++++++++++----
>  server/red_dispatcher.c    |  2 +-
>  server/video_encoder.h     |  2 +-
>  5 files changed, 112 insertions(+), 14 deletions(-)
> 
> diff --git a/configure.ac b/configure.ac
> index 3c1882f..eca8295 100644
> --- a/configure.ac
> +++ b/configure.ac
> @@ -82,14 +82,14 @@ 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 1.0 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="yes"
> +                      [enable_gstreamer="1.0"
>                         have_gstreamer_1_0="yes"],
>                        [have_gstreamer_1_0="no"])
>      if test "x$have_gstreamer_1_0" = "xyes"; then
> @@ -97,7 +97,7 @@ if test "x$enable_gstreamer" != "xno"; then
>          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" = "xyes"; then
> +    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
> @@ -105,6 +105,29 @@ else
>  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="0.10"
> +                       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" = "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
> +    have_gstreamer_0_10="no"
> +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"])
> @@ -334,7 +357,7 @@ echo "
>  
>          Smartcard:                ${have_smartcard}
>  
> -        GStreamer 1.0:            ${have_gstreamer_1_0}
> +        GStreamer:                ${enable_gstreamer}
>  
>          SASL support:             ${enable_sasl}
>  
> diff --git a/server/Makefile.am b/server/Makefile.am
> index 60c2036..0fa8d19 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)		\
>  	$(GSTREAMER_1_0_CFLAGS)			\
>  	$(SPICE_PROTOCOL_CFLAGS)		\
>  	$(SSL_CFLAGS)				\
> @@ -43,6 +44,7 @@ libspice_server_la_LIBADD =						\
>  	$(PIXMAN_LIBS)							\
>  	$(SASL_LIBS)							\
>  	$(SLIRP_LIBS)							\
> +	$(GSTREAMER_0_10_LIBS)						\
>  	$(GSTREAMER_1_0_LIBS)						\
>  	$(SSL_LIBS)							\
>  	$(Z_LIBS)							\
> @@ -146,6 +148,12 @@ libspice_server_la_SOURCES +=	\
>  	$(NULL)
>  endif
>  
> +if SUPPORT_GSTREAMER_0_10
> +libspice_server_la_SOURCES +=	\
> +	gstreamer_encoder.c			\
> +	$(NULL)
> +endif
> +
>  if SUPPORT_GSTREAMER_1_0
>  libspice_server_la_SOURCES +=	\
>  	gstreamer_encoder.c			\
> diff --git a/server/gstreamer_encoder.c b/server/gstreamer_encoder.c
> index 82f6aee..8694f23 100644
> --- a/server/gstreamer_encoder.c
> +++ b/server/gstreamer_encoder.c
> @@ -32,7 +32,9 @@
>  
>  #define GSTE_DEFAULT_FPS 30
>  
> -#define DO_ZERO_COPY
> +#ifndef HAVE_GSTREAMER_0_10
> +# define DO_ZERO_COPY
> +#endif
>  
>  #define NANO_SECOND (1000000000LL)
>  #define MILLI_SECOND (1000LL)
> @@ -42,12 +44,19 @@ typedef struct {
>      SpiceBitmapFmt spice_format;
>      const char *format;
>      uint32_t bpp;
> +    uint32_t depth;
> +    uint32_t endianness;
> +    uint32_t blue_mask;
> +    uint32_t green_mask;
> +    uint32_t red_mask;
>  } SpiceFormatForGStreamer;
>  
>  typedef struct SpiceGstVideoBuffer {
>      VideoBuffer base;
>      GstBuffer *gst_buffer;
> +#ifndef HAVE_GSTREAMER_0_10
>      GstMapInfo map;
> +#endif
>  } SpiceGstVideoBuffer;
>  
>  typedef struct {
> @@ -265,6 +274,9 @@ typedef struct SpiceGstEncoder {
>  static void gst_video_buffer_free(VideoBuffer *video_buffer)
>  {
>      SpiceGstVideoBuffer *buffer = (SpiceGstVideoBuffer*)video_buffer;
> +#ifndef HAVE_GSTREAMER_0_10
> +        gst_buffer_unmap(buffer->gst_buffer, &buffer->map);
> +#endif
>      gst_buffer_unref(buffer->gst_buffer);
>      free(buffer);
>  }
> @@ -694,11 +706,11 @@ static SpiceFormatForGStreamer *map_format(SpiceBitmapFmt format)
>       * section-types-definitions.html documents.
>       */
>      static SpiceFormatForGStreamer format_map[] =  {
> -        {SPICE_BITMAP_FMT_RGBA, "BGRA", 32},
> +        {SPICE_BITMAP_FMT_RGBA, "BGRA", 32, 24, 4321, 0xff000000, 0xff0000, 0xff00},
>          /* TODO: Test the other formats */
> -        {SPICE_BITMAP_FMT_32BIT, "BGRx", 32},
> -        {SPICE_BITMAP_FMT_24BIT, "BGR", 24},
> -        {SPICE_BITMAP_FMT_16BIT, "BGR15", 16},
> +        {SPICE_BITMAP_FMT_32BIT, "BGRx", 32, 24, 4321, 0xff000000, 0xff0000, 0xff00},
> +        {SPICE_BITMAP_FMT_24BIT, "BGR", 24, 24, 4321, 0xff0000, 0xff00, 0xff},
> +        {SPICE_BITMAP_FMT_16BIT, "BGR15", 16, 15, 4321, 0x001f, 0x03E0, 0x7C00},
>      };
>  
>      int i;
> @@ -717,8 +729,18 @@ static void set_appsrc_caps(SpiceGstEncoder *encoder)
>          gst_caps_unref(encoder->src_caps);
>      }
>      encoder->src_caps = gst_caps_new_simple(
> +#ifdef HAVE_GSTREAMER_0_10
> +        "video/x-raw-rgb",
> +        "bpp", G_TYPE_INT, encoder->format->bpp,
> +        "depth", G_TYPE_INT, encoder->format->depth,
> +        "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,
> +#else
>          "video/x-raw",
>          "format", G_TYPE_STRING, encoder->format->format,
> +#endif
>          "width", G_TYPE_INT, encoder->width,
>          "height", G_TYPE_INT, encoder->height,
>          "framerate", GST_TYPE_FRACTION, get_source_fps(encoder), 1,
> @@ -731,7 +753,11 @@ static const gchar* get_gst_codec_name(SpiceGstEncoder *encoder)
>      switch (encoder->base.codec_type)
>      {
>      case SPICE_VIDEO_CODEC_TYPE_MJPEG:
> +#ifdef HAVE_GSTREAMER_0_10
> +        return "ffenc_mjpeg";
> +#else
>          return "avenc_mjpeg";
> +#endif
>      case SPICE_VIDEO_CODEC_TYPE_VP8:
>          return "vp8enc";
>      case SPICE_VIDEO_CODEC_TYPE_H264:
> @@ -809,9 +835,14 @@ static gboolean construct_pipeline(SpiceGstEncoder *encoder, const SpiceBitmap *
>      if (!gstenc_name) {
>          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 ! videoconvert ! %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);
> @@ -846,10 +877,17 @@ static gboolean construct_pipeline(SpiceGstEncoder *encoder, const SpiceBitmap *
>          g_object_set(G_OBJECT(encoder->gstenc),
>                       "resize-allowed", TRUE, /* for very low bit rates */
>                       "min-quantizer", 10, /* seems virtually lossless */
> +#ifdef HAVE_GSTREAMER_0_10
> +                     "mode", 1, /* CBR */
> +                     "max-latency", 0, /* zero-frame latency */
> +                     "error-resilient", TRUE, /* for client frame drops */
> +                     "speed", 7, /* ultrafast */
> +#else
>                       "end-usage", 1, /* CBR */
>                       "lag-in-frames", 0, /* zero-frame latency */
>                       "error-resilient", 1, /* for client frame drops */
>                       "deadline", 1000000 / get_source_fps(encoder) / 2, /* usec */
> +#endif
>                       "threads", core_count - 1,
>                       NULL);
>          break;
> @@ -1025,9 +1063,14 @@ static int push_raw_frame(SpiceGstEncoder *encoder, const SpiceBitmap *bitmap,
>      const uint32_t height = src->bottom - src->top;
>      const uint32_t stream_stride = (src->right - src->left) * encoder->format->bpp / 8;
>      uint32_t len = stream_stride * height;
> +#ifdef HAVE_GSTREAMER_0_10
> +    GstBuffer *buffer = gst_buffer_new_and_alloc(len);
> +    uint8_t *dst = GST_BUFFER_DATA(buffer);
> +#else
>      GstBuffer *buffer = gst_buffer_new();
>      /* TODO Use GST_MAP_INFO_INIT once GStreamer 1.4.5 is no longer relevant */
>      GstMapInfo map = { .memory = NULL };
> +#endif
>  
>      /* 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.
> @@ -1039,6 +1082,7 @@ static int push_raw_frame(SpiceGstEncoder *encoder, const SpiceBitmap *bitmap,
>          /* We have to do a line-by-line copy because for each we have to leave
>           * out pixels on the left or right.
>           */
> +#ifndef HAVE_GSTREAMER_0_10
>          GstMemory *mem = gst_allocator_alloc(NULL, len, NULL);
>          if (!mem) {
>              gst_buffer_unref(buffer);
> @@ -1046,11 +1090,14 @@ static int push_raw_frame(SpiceGstEncoder *encoder, const SpiceBitmap *bitmap,
>          }
>          spice_assert(gst_memory_map(mem, &map, GST_MAP_WRITE));
>          uint8_t *dst = map.data;
> +#endif
>  
>          chunk_offset += src->left * encoder->format->bpp / 8;
>          if (!line_copy(encoder, bitmap, chunk_offset, stream_stride, height, dst)) {
> +#ifndef HAVE_GSTREAMER_0_10
>              gst_memory_unmap(map.memory, &map);
>              gst_memory_unref(map.memory);
> +#endif
>              gst_buffer_unref(buffer);
>              return VIDEO_ENCODER_FRAME_UNSUPPORTED;
>          }
> @@ -1070,6 +1117,7 @@ static int push_raw_frame(SpiceGstEncoder *encoder, const SpiceBitmap *bitmap,
>           */
>  #endif
>  
> +#ifndef HAVE_GSTREAMER_0_10
>          if (len) {
>              GstMemory *mem = gst_allocator_alloc(NULL, len, NULL);
>              if (!mem) {
> @@ -1079,12 +1127,15 @@ static int push_raw_frame(SpiceGstEncoder *encoder, const SpiceBitmap *bitmap,
>              spice_assert(gst_memory_map(mem, &map, GST_MAP_WRITE));
>          }
>          uint8_t *dst = map.data;
> +#endif
>  
>          while (len && chunk_index < chunks->num_chunks) {
>              /* Make sure that the chunk is not padded */
>              if (chunks->chunk[chunk_index].len % bitmap->stride != 0) {
> +#ifndef HAVE_GSTREAMER_0_10
>                  gst_memory_unmap(map.memory, &map);
>                  gst_memory_unref(map.memory);
> +#endif
>                  gst_buffer_unref(buffer);
>                  spice_warning("chunk %d/%d is padded, cannot copy it",
>                                chunk_index, chunks->num_chunks);
> @@ -1106,10 +1157,14 @@ static int push_raw_frame(SpiceGstEncoder *encoder, const SpiceBitmap *bitmap,
>          }
>          spice_assert(len == 0);
>      }
> +#ifdef HAVE_GSTREAMER_0_10
> +    gst_buffer_set_caps(buffer, encoder->src_caps);
> +#else
>      if (map.memory) {
>          gst_memory_unmap(map.memory, &map);
>          gst_buffer_append_memory(buffer, map.memory);
>      }
> +#endif
>      GST_BUFFER_OFFSET(buffer) = encoder->frame++;
>  
>      GstFlowReturn ret = gst_app_src_push_buffer(encoder->appsrc, buffer);
> @@ -1125,6 +1180,17 @@ static int push_raw_frame(SpiceGstEncoder *encoder, const SpiceBitmap *bitmap,
>  static int pull_compressed_buffer(SpiceGstEncoder *encoder,
>                                    VideoBuffer **video_buffer)
>  {
> +#ifdef HAVE_GSTREAMER_0_10
> +    SpiceGstVideoBuffer *buffer = create_gst_video_buffer();
> +    buffer->gst_buffer = gst_app_sink_pull_buffer(encoder->appsink);
> +    if (buffer->gst_buffer) {
> +        buffer->base.data = GST_BUFFER_DATA(buffer->gst_buffer);
> +        buffer->base.size = GST_BUFFER_SIZE(buffer->gst_buffer);
> +        *video_buffer = (VideoBuffer*)buffer;
> +        return VIDEO_ENCODER_FRAME_ENCODE_DONE;
> +    }
> +    buffer->base.free((VideoBuffer*)buffer);
> +#else
>      GstSample *sample = gst_app_sink_pull_sample(encoder->appsink);
>      if (sample) {
>          SpiceGstVideoBuffer *buffer = create_gst_video_buffer();
> @@ -1141,6 +1207,7 @@ static int pull_compressed_buffer(SpiceGstEncoder *encoder,
>          buffer->base.free((VideoBuffer*)buffer);
>          gst_sample_unref(sample);
>      }
> +#endif
>      spice_debug("failed to pull the compressed buffer");
>      return VIDEO_ENCODER_FRAME_UNSUPPORTED;
>  }
> diff --git a/server/red_dispatcher.c b/server/red_dispatcher.c
> index 60eef24..1ada928 100644
> --- a/server/red_dispatcher.c
> +++ b/server/red_dispatcher.c
> @@ -258,7 +258,7 @@ static const EnumNames video_encoder_names[] = {
>  
>  static new_video_encoder_t video_encoder_procs[] = {
>      &mjpeg_encoder_new,
> -#ifdef HAVE_GSTREAMER_1_0
> +#if defined(HAVE_GSTREAMER_1_0) || defined(HAVE_GSTREAMER_0_10)
>      &gstreamer_encoder_new,
>  #else
>      NULL,
> diff --git a/server/video_encoder.h b/server/video_encoder.h
> index 0214893..c497e88 100644
> --- a/server/video_encoder.h
> +++ b/server/video_encoder.h
> @@ -180,7 +180,7 @@ VideoEncoder* mjpeg_encoder_new(SpiceVideoCodecType codec_type,
>                                  uint64_t starting_bit_rate,
>                                  VideoEncoderRateControlCbs *cbs,
>                                  void *cbs_opaque);
> -#ifdef HAVE_GSTREAMER_1_0
> +#if defined(HAVE_GSTREAMER_1_0) || defined(HAVE_GSTREAMER_0_10)
>  VideoEncoder* gstreamer_encoder_new(SpiceVideoCodecType codec_type,
>                                      uint64_t starting_bit_rate,
>                                      VideoEncoderRateControlCbs *cbs,
> -- 
> 2.6.1
> _______________________________________________
> Spice-devel mailing list
> Spice-devel@lists.freedesktop.org
> http://lists.freedesktop.org/mailman/listinfo/spice-devel
On Thu, 22 Oct 2015, Christophe Fergeau wrote:

> 
> Ah, now I see it's this patch which needs to disable zero copy. ACK.

That and it's useful to be able to disable zero-copy for testing or 
debugging purposes.