[Spice-devel,v16,14/23] streaming: Add h264 support to the GStreamer video encoder

Submitted by Francois Gouget on June 7, 2016, 1:59 p.m.

Details

Message ID 454ad5dbcc94d02650f56e9cc428c663e731356f.1465306176.git.fgouget@free.fr
State New
Headers show
Series "Add GStreamer support for video streaming" ( rev: 22 21 20 19 18 ) in Spice

Not browsing as part of any series.

Commit Message

Francois Gouget June 7, 2016, 1:59 p.m.
Signed-off-by: Francois Gouget <fgouget@codeweavers.com>
---
 configure.ac               |  1 +
 server/gstreamer-encoder.c | 17 ++++++++++++++++-
 server/reds.c              |  4 +++-
 3 files changed, 20 insertions(+), 2 deletions(-)

Patch hide | download patch | download mbox

diff --git a/configure.ac b/configure.ac
index 650ea4a..1cc9f4f 100644
--- a/configure.ac
+++ b/configure.ac
@@ -79,6 +79,7 @@  if test "x$enable_gstreamer" != "xno"; then
          SPICE_CHECK_GSTREAMER_ELEMENTS($GST_INSPECT_1_0, [gst-plugins-base 1.0], [appsrc videoconvert appsink])
          SPICE_CHECK_GSTREAMER_ELEMENTS($GST_INSPECT_1_0, [gstreamer-libav 1.0], [avenc_mjpeg])
          SPICE_CHECK_GSTREAMER_ELEMENTS($GST_INSPECT_1_0, [gst-plugins-good 1.0], [vp8enc])
+         SPICE_CHECK_GSTREAMER_ELEMENTS($GST_INSPECT_1_0, [gst-plugins-ugly 1.0], [x264enc])
          ],
          [if test "x$enable_gstreamer" = "xyes"; 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.])
diff --git a/server/gstreamer-encoder.c b/server/gstreamer-encoder.c
index a698bb1..07bdd4e 100644
--- a/server/gstreamer-encoder.c
+++ b/server/gstreamer-encoder.c
@@ -334,6 +334,15 @@  static gboolean create_pipeline(SpiceGstEncoder *encoder)
         gstenc = g_strdup_printf("vp8enc end-usage=cbr min-quantizer=10 error-resilient=default lag-in-frames=0 deadline=1 cpu-used=4 threads=%d token-partitions=%d", threads, parts);
         break;
         }
+    case SPICE_VIDEO_CODEC_TYPE_H264:
+        /* - Set tune and sliced-threads to ensure a zero-frame latency
+         * - qp-min ensures the bitrate does not get needlessly high.
+         * - Set speed-preset to get realtime speed.
+         * - Set intra-refresh to get more uniform compressed frame sizes,
+         *   thus helping with streaming.
+         */
+        gstenc = g_strdup("x264enc byte-stream=true aud=true qp-min=15 tune=4 sliced-threads=true speed-preset=ultrafast intra-refresh=true");
+        break;
     default:
         /* gstreamer_encoder_new() should have rejected this codec type */
         spice_warning("unsupported codec type %d", encoder->base.codec_type);
@@ -404,6 +413,11 @@  static void set_gstenc_bitrate(SpiceGstEncoder *encoder)
                      "target-bitrate", (gint)encoder->bit_rate,
                      NULL);
         break;
+    case SPICE_VIDEO_CODEC_TYPE_H264:
+        g_object_set(G_OBJECT(encoder->gstenc),
+                     "bitrate", encoder->bit_rate / 1024,
+                     NULL);
+        break;
     default:
         /* gstreamer_encoder_new() should have rejected this codec type */
         spice_warning("unsupported codec type %d", encoder->base.codec_type);
@@ -864,7 +878,8 @@  VideoEncoder *gstreamer_encoder_new(SpiceVideoCodecType codec_type,
                                     bitmap_unref_t bitmap_unref)
 {
     spice_return_val_if_fail(codec_type == SPICE_VIDEO_CODEC_TYPE_MJPEG ||
-                             codec_type == SPICE_VIDEO_CODEC_TYPE_VP8, NULL);
+                             codec_type == SPICE_VIDEO_CODEC_TYPE_VP8 ||
+                             codec_type == SPICE_VIDEO_CODEC_TYPE_H264, NULL);
 
     GError *err = NULL;
     if (!gst_init_check(NULL, NULL, &err)) {
diff --git a/server/reds.c b/server/reds.c
index 21d3835..0e320e8 100644
--- a/server/reds.c
+++ b/server/reds.c
@@ -3499,7 +3499,7 @@  err:
 }
 
 static const char default_renderer[] = "sw";
-static const char default_video_codecs[] = "spice:mjpeg;gstreamer:mjpeg;gstreamer:vp8";
+static const char default_video_codecs[] = "spice:mjpeg;gstreamer:mjpeg;gstreamer:h264;gstreamer:vp8";
 
 /* new interface */
 SPICE_GNUC_VISIBLE SpiceServer *spice_server_new(void)
@@ -3587,12 +3587,14 @@  static new_video_encoder_t 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 int video_codec_caps[] = {
     SPICE_DISPLAY_CAP_CODEC_MJPEG,
     SPICE_DISPLAY_CAP_CODEC_VP8,
+    SPICE_DISPLAY_CAP_CODEC_H264,
 };