[Spice-devel] [PATCH v6 19/26] server: Add support for GStreamer 0.10
Christophe Fergeau
cfergeau at redhat.com
Thu Oct 22 10:05:28 PDT 2015
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 at 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 at lists.freedesktop.org
> http://lists.freedesktop.org/mailman/listinfo/spice-devel
-------------- next part --------------
A non-text attachment was scrubbed...
Name: signature.asc
Type: application/pgp-signature
Size: 819 bytes
Desc: not available
URL: <http://lists.freedesktop.org/archives/spice-devel/attachments/20151022/6f49d275/attachment.sig>
More information about the Spice-devel
mailing list