[Date Prev][Date Next]   [Thread Prev][Thread Next]   [Thread Index] [Date Index] [Author Index]

[libvirt] [PATCH] Spice: support auid, images and stream compression



This extends the SPICE XML to allow variable compression settings for audio,
images and streaming:
    <graphics type='spice' port='5901' tlsPort='-1' autoport='yes'>
        <image compression='auto_glz'/>
        <jpeg compression='auto'/>
        <zlib compression='auto'/>
        <playback compression='on'/>
    </graphics>

All new element are optional.
---
 docs/formatdomain.html.in                          |   12 ++
 docs/schemas/domain.rng                            |   50 ++++++++
 src/conf/domain_conf.c                             |  130 ++++++++++++++++++++
 src/conf/domain_conf.h                             |   42 +++++++
 src/libvirt_private.syms                           |    8 ++
 src/qemu/qemu_command.c                            |   16 +++
 .../qemuxml2argv-graphics-spice.args               |    4 +-
 .../qemuxml2argv-graphics-spice.xml                |    4 +
 8 files changed, 265 insertions(+), 1 deletions(-)

diff --git a/docs/formatdomain.html.in b/docs/formatdomain.html.in
index 3c4c656..c5edf53 100644
--- a/docs/formatdomain.html.in
+++ b/docs/formatdomain.html.in
@@ -1664,6 +1664,18 @@ qemu-kvm -net nic,model=? /dev/null
     &lt;channel name='main' mode='secure'/&gt;
     &lt;channel name='record' mode='insecure'/&gt;
   &lt;/graphics&gt;</pre>
+            <p>
+Spice supports variable compression settings for audio, images and streaming.
+This setting are accessible via <code>compression</code> attribute in all
+following elements: <code>image</code> to set image compression (accept
+<code>auto_glz</code>, <code>auto_lz</code>, <code>quic</code>,
+<code>glz</code>, <code>lz</code>, <code>off</code>), <code>jpeg</code> for
+JPEG compression for images over wan (accept <code>auto</code>,
+<code>never</code>, <code>always</code>), <code>zlib</code> for configuring
+wan image compression (accept <code>auto</code>, <code>never</code>,
+<code>always</code>) and <code>playback</code> for enabling audio stream
+compression (accept <code>on</code> or <code>off</code>)
+            </p>
           </dd>
           <dt><code>"rdp"</code></dt>
           <dd>
diff --git a/docs/schemas/domain.rng b/docs/schemas/domain.rng
index 0fbf326..f0578f8 100644
--- a/docs/schemas/domain.rng
+++ b/docs/schemas/domain.rng
@@ -1283,6 +1283,56 @@
               <empty/>
             </element>
           </zeroOrMore>
+          <optional>
+            <element name="image">
+              <attribute name="compression">
+                <choice>
+                  <value>auto_glz</value>
+                  <value>auto_lz</value>
+                  <value>quic</value>
+                  <value>glz</value>
+                  <value>lz</value>
+                  <value>off</value>
+                </choice>
+              </attribute>
+              <empty/>
+            </element>
+          </optional>
+          <optional>
+            <element name="jpeg">
+              <attribute name="compression">
+                <choice>
+                  <value>auto</value>
+                  <value>never</value>
+                  <value>always</value>
+                </choice>
+              </attribute>
+              <empty/>
+            </element>
+          </optional>
+          <optional>
+            <element name="zlib">
+              <attribute name="compression">
+                <choice>
+                  <value>auto</value>
+                  <value>never</value>
+                  <value>always</value>
+                </choice>
+              </attribute>
+              <empty/>
+            </element>
+          </optional>
+          <optional>
+            <element name="playback">
+              <attribute name="compression">
+                <choice>
+                  <value>on</value>
+                  <value>off</value>
+                </choice>
+              </attribute>
+              <empty/>
+            </element>
+          </optional>
         </group>
         <group>
           <attribute name="type">
diff --git a/src/conf/domain_conf.c b/src/conf/domain_conf.c
index 90a1317..f215e7d 100644
--- a/src/conf/domain_conf.c
+++ b/src/conf/domain_conf.c
@@ -322,6 +322,32 @@ VIR_ENUM_IMPL(virDomainGraphicsSpiceChannelMode,
               "secure",
               "insecure");
 
+VIR_ENUM_IMPL(virDomainGraphicsSpiceImageCompression,
+              VIR_DOMAIN_GRAPHICS_SPICE_IMAGE_COMPRESSION_LAST,
+              "auto_glz",
+              "auto_lz",
+              "quic",
+              "glz",
+              "lz",
+              "off");
+
+VIR_ENUM_IMPL(virDomainGraphicsSpiceJpegCompression,
+              VIR_DOMAIN_GRAPHICS_SPICE_JPEG_COMPRESSION_LAST,
+              "auto",
+              "never",
+              "always");
+
+VIR_ENUM_IMPL(virDomainGraphicsSpiceZlibCompression,
+              VIR_DOMAIN_GRAPHICS_SPICE_ZLIB_COMPRESSION_LAST,
+              "auto",
+              "never",
+              "always");
+
+VIR_ENUM_IMPL(virDomainGraphicsSpicePlaybackCompression,
+              VIR_DOMAIN_GRAPHICS_SPICE_PLAYBACK_COMPRESSION_LAST,
+              "on",
+              "off");
+
 VIR_ENUM_IMPL(virDomainHostdevMode, VIR_DOMAIN_HOSTDEV_MODE_LAST,
               "subsystem",
               "capabilities")
@@ -3917,6 +3943,11 @@ virDomainGraphicsDefParseXML(xmlNodePtr node, int flags) {
         if (virDomainGraphicsAuthDefParseXML(node, &def->data.spice.auth) < 0)
             goto error;
 
+        def->data.spice.image = VIR_DOMAIN_GRAPHICS_SPICE_IMAGE_COMPRESSION_LAST;
+        def->data.spice.jpeg = VIR_DOMAIN_GRAPHICS_SPICE_JPEG_COMPRESSION_LAST;
+        def->data.spice.zlib = VIR_DOMAIN_GRAPHICS_SPICE_ZLIB_COMPRESSION_LAST;
+        def->data.spice.playback = VIR_DOMAIN_GRAPHICS_SPICE_PLAYBACK_COMPRESSION_LAST;
+
         cur = node->children;
         while (cur != NULL) {
             if (cur->type == XML_ELEMENT_NODE) {
@@ -3954,6 +3985,89 @@ virDomainGraphicsDefParseXML(xmlNodePtr node, int flags) {
                     VIR_FREE(mode);
 
                     def->data.spice.channels[nameval] = modeval;
+                } else if (xmlStrEqual(cur->name, BAD_CAST "image")) {
+                    const char *compression = virXMLPropString(cur, "compression");
+                    int compressionVal;
+
+                    if (!compression) {
+                        virDomainReportError(VIR_ERR_INTERNAL_ERROR, "%s",
+                                             _("spice image missing compression"));
+                        goto error;
+                    }
+
+                    if ((compressionVal =
+                         virDomainGraphicsSpiceImageCompressionTypeFromString(compression)) < 0) {
+                        virDomainReportError(VIR_ERR_INTERNAL_ERROR,
+                                             _("unknown spice image compression %s"),
+                                             compression);
+                        VIR_FREE(compression);
+                        goto error;
+                    }
+                    VIR_FREE(compression);
+
+                    def->data.spice.image = compressionVal;
+                } else if (xmlStrEqual(cur->name, BAD_CAST "jpeg")) {
+                    const char *compression = virXMLPropString(cur, "compression");
+                    int compressionVal;
+
+                    if (!compression) {
+                        virDomainReportError(VIR_ERR_INTERNAL_ERROR, "%s",
+                                             _("spice jpeg missing compression"));
+                        goto error;
+                    }
+
+                    if ((compressionVal =
+                         virDomainGraphicsSpiceJpegCompressionTypeFromString(compression)) < 0) {
+                        virDomainReportError(VIR_ERR_INTERNAL_ERROR,
+                                             _("unknown spice jpeg compression %s"),
+                                             compression);
+                        VIR_FREE(compression);
+                        goto error;
+                    }
+                    VIR_FREE(compression);
+
+                    def->data.spice.jpeg = compressionVal;
+                } else if (xmlStrEqual(cur->name, BAD_CAST "zlib")) {
+                    const char *compression = virXMLPropString(cur, "compression");
+                    int compressionVal;
+
+                    if (!compression) {
+                        virDomainReportError(VIR_ERR_INTERNAL_ERROR, "%s",
+                                             _("spice zlib missing compression"));
+                        goto error;
+                    }
+
+                    if ((compressionVal =
+                         virDomainGraphicsSpiceZlibCompressionTypeFromString(compression)) < 0) {
+                        virDomainReportError(VIR_ERR_INTERNAL_ERROR,
+                                             _("unknown spice zlib compression %s"),
+                                             compression);
+                        VIR_FREE(compression);
+                        goto error;
+                    }
+
+                    def->data.spice.zlib = compressionVal;
+                } else if (xmlStrEqual(cur->name, BAD_CAST "playback")) {
+                    const char *compression = virXMLPropString(cur, "compression");
+                    int compressionVal;
+
+                    if (!compression) {
+                        virDomainReportError(VIR_ERR_INTERNAL_ERROR, "%s",
+                                             _("spice playback missing compression"));
+                        goto error;
+                    }
+
+                    if ((compressionVal =
+                         virDomainGraphicsSpicePlaybackCompressionTypeFromString(compression)) < 0) {
+                        virDomainReportError(VIR_ERR_INTERNAL_ERROR,
+                                             _("unknown spice playback compression"));
+                        VIR_FREE(compression);
+                        goto error;
+
+                    }
+                    VIR_FREE(compression);
+
+                    def->data.spice.playback = compressionVal;
                 }
             }
             cur = cur->next;
@@ -7817,6 +7931,22 @@ virDomainGraphicsDefFormat(virBufferPtr buf,
                               virDomainGraphicsSpiceChannelNameTypeToString(i),
                               virDomainGraphicsSpiceChannelModeTypeToString(mode));
         }
+        if (def->data.spice.image !=
+            VIR_DOMAIN_GRAPHICS_SPICE_IMAGE_COMPRESSION_LAST)
+            virBufferVSprintf(buf, "      <image compression='%s'/>\n",
+                              virDomainGraphicsSpiceImageCompressionTypeToString(def->data.spice.image));
+        if (def->data.spice.jpeg !=
+            VIR_DOMAIN_GRAPHICS_SPICE_JPEG_COMPRESSION_LAST)
+            virBufferVSprintf(buf, "      <jpeg compression='%s'/>\n",
+                              virDomainGraphicsSpiceJpegCompressionTypeToString(def->data.spice.jpeg));
+        if (def->data.spice.zlib !=
+            VIR_DOMAIN_GRAPHICS_SPICE_ZLIB_COMPRESSION_LAST)
+            virBufferVSprintf(buf, "      <zlib compression='%s'/>\n",
+                              virDomainGraphicsSpiceZlibCompressionTypeToString(def->data.spice.zlib));
+        if (def->data.spice.playback !=
+            VIR_DOMAIN_GRAPHICS_SPICE_PLAYBACK_COMPRESSION_LAST)
+            virBufferVSprintf(buf, "      <playback compression='%s'/>\n",
+                              virDomainGraphicsSpicePlaybackCompressionTypeToString(def->data.spice.playback));
     }
 
     if (children) {
diff --git a/src/conf/domain_conf.h b/src/conf/domain_conf.h
index 95bd11e..e36f0ed 100644
--- a/src/conf/domain_conf.h
+++ b/src/conf/domain_conf.h
@@ -658,6 +658,40 @@ enum virDomainGraphicsSpiceChannelMode {
     VIR_DOMAIN_GRAPHICS_SPICE_CHANNEL_MODE_LAST
 };
 
+enum virDomainGraphicsSpiceImageCompression {
+    VIR_DOMAIN_GRAPHICS_SPICE_IMAGE_COMPRESSION_AUTO_GLZ,
+    VIR_DOMAIN_GRAPHICS_SPICE_IMAGE_COMPRESSION_AUTO_LZ,
+    VIR_DOMAIN_GRAPHICS_SPICE_IMAGE_COMPRESSION_QUIC,
+    VIR_DOMAIN_GRAPHICS_SPICE_IMAGE_COMPRESSION_GLZ,
+    VIR_DOMAIN_GRAPHICS_SPICE_IMAGE_COMPRESSION_LZ,
+    VIR_DOMAIN_GRAPHICS_SPICE_IMAGE_COMPRESSION_OFF,
+
+    VIR_DOMAIN_GRAPHICS_SPICE_IMAGE_COMPRESSION_LAST
+};
+
+enum virDomainGraphicsSpiceJpegCompression {
+    VIR_DOMAIN_GRAPHICS_SPICE_JPEG_COMPRESSION_AUTO,
+    VIR_DOMAIN_GRAPHICS_SPICE_JPEG_COMPRESSION_NEVER,
+    VIR_DOMAIN_GRAPHICS_SPICE_JPEG_COMPRESSION_ALWAYS,
+
+    VIR_DOMAIN_GRAPHICS_SPICE_JPEG_COMPRESSION_LAST
+};
+
+enum virDomainGraphicsSpiceZlibCompression {
+    VIR_DOMAIN_GRAPHICS_SPICE_ZLIB_COMPRESSION_AUTO,
+    VIR_DOMAIN_GRAPHICS_SPICE_ZLIB_COMPRESSION_NEVER,
+    VIR_DOMAIN_GRAPHICS_SPICE_ZLIB_COMPRESSION_ALWAYS,
+
+    VIR_DOMAIN_GRAPHICS_SPICE_ZLIB_COMPRESSION_LAST
+};
+
+enum virDomainGraphicsSpicePlaybackCompression {
+    VIR_DOMAIN_GRAPHICS_SPICE_PLAYBACK_COMPRESSION_ON,
+    VIR_DOMAIN_GRAPHICS_SPICE_PLAYBACK_COMPRESSION_OFF,
+
+    VIR_DOMAIN_GRAPHICS_SPICE_PLAYBACK_COMPRESSION_LAST
+};
+
 typedef struct _virDomainGraphicsDef virDomainGraphicsDef;
 typedef virDomainGraphicsDef *virDomainGraphicsDefPtr;
 struct _virDomainGraphicsDef {
@@ -695,6 +729,10 @@ struct _virDomainGraphicsDef {
             virDomainGraphicsAuthDef auth;
             unsigned int autoport :1;
             int channels[VIR_DOMAIN_GRAPHICS_SPICE_CHANNEL_LAST];
+            int image;
+            int jpeg;
+            int zlib;
+            int playback;
         } spice;
     } data;
 };
@@ -1423,6 +1461,10 @@ VIR_ENUM_DECL(virDomainInputBus)
 VIR_ENUM_DECL(virDomainGraphics)
 VIR_ENUM_DECL(virDomainGraphicsSpiceChannelName)
 VIR_ENUM_DECL(virDomainGraphicsSpiceChannelMode)
+VIR_ENUM_DECL(virDomainGraphicsSpiceImageCompression)
+VIR_ENUM_DECL(virDomainGraphicsSpiceJpegCompression)
+VIR_ENUM_DECL(virDomainGraphicsSpiceZlibCompression)
+VIR_ENUM_DECL(virDomainGraphicsSpicePlaybackCompression)
 /* from libvirt.h */
 VIR_ENUM_DECL(virDomainState)
 VIR_ENUM_DECL(virDomainSeclabel)
diff --git a/src/libvirt_private.syms b/src/libvirt_private.syms
index 54e4482..d2aa077 100644
--- a/src/libvirt_private.syms
+++ b/src/libvirt_private.syms
@@ -262,6 +262,14 @@ virDomainGraphicsSpiceChannelModeTypeFromString;
 virDomainGraphicsSpiceChannelModeTypeToString;
 virDomainGraphicsSpiceChannelNameTypeFromString;
 virDomainGraphicsSpiceChannelNameTypeToString;
+virDomainGraphicsSpiceImageCompressionTypeToString;
+virDomainGraphicsSpiceImageCompressionTypeFromString;
+virDomainGraphicsSpiceJpegCompressionTypeFromString;
+virDomainGraphicsSpiceJpegCompressionTypeToString;
+virDomainGraphicsSpicePlaybackCompressionTypeFromString;
+virDomainGraphicsSpicePlaybackCompressionTypeToString;
+virDomainGraphicsSpiceZlibCompressionTypeFromString;
+virDomainGraphicsSpiceZlibCompressionTypeToString;
 virDomainGraphicsTypeFromString;
 virDomainGraphicsTypeToString;
 virDomainHostdevDefFree;
diff --git a/src/qemu/qemu_command.c b/src/qemu/qemu_command.c
index fea0068..6272910 100644
--- a/src/qemu/qemu_command.c
+++ b/src/qemu/qemu_command.c
@@ -4032,6 +4032,22 @@ qemuBuildCommandLine(virConnectPtr conn,
                 break;
             }
         }
+        if (def->graphics[0]->data.spice.image !=
+            VIR_DOMAIN_GRAPHICS_SPICE_IMAGE_COMPRESSION_LAST)
+            virBufferVSprintf(&opt, ",image-compression=%s",
+                              virDomainGraphicsSpiceImageCompressionTypeToString(def->graphics[0]->data.spice.image));
+        if (def->graphics[0]->data.spice.jpeg !=
+            VIR_DOMAIN_GRAPHICS_SPICE_JPEG_COMPRESSION_LAST)
+            virBufferVSprintf(&opt, ",jpeg-wan-compression=%s",
+                              virDomainGraphicsSpiceJpegCompressionTypeToString(def->graphics[0]->data.spice.jpeg));
+        if (def->graphics[0]->data.spice.zlib !=
+            VIR_DOMAIN_GRAPHICS_SPICE_ZLIB_COMPRESSION_LAST)
+            virBufferVSprintf(&opt, ",zlib-glz-wan-compression=%s",
+                              virDomainGraphicsSpiceZlibCompressionTypeToString(def->graphics[0]->data.spice.zlib));
+        if (def->graphics[0]->data.spice.playback !=
+            VIR_DOMAIN_GRAPHICS_SPICE_PLAYBACK_COMPRESSION_LAST)
+            virBufferVSprintf(&opt, ",playback-compression=%s",
+                              virDomainGraphicsSpicePlaybackCompressionTypeToString(def->graphics[0]->data.spice.playback));
 
         virCommandAddArg(cmd, "-spice");
         virCommandAddArgBuffer(cmd, &opt);
diff --git a/tests/qemuxml2argvdata/qemuxml2argv-graphics-spice.args b/tests/qemuxml2argvdata/qemuxml2argv-graphics-spice.args
index c788bb6..70cd35b 100644
--- a/tests/qemuxml2argvdata/qemuxml2argv-graphics-spice.args
+++ b/tests/qemuxml2argvdata/qemuxml2argv-graphics-spice.args
@@ -2,6 +2,8 @@ LC_ALL=C PATH=/bin HOME=/home/test USER=test LOGNAME=test QEMU_AUDIO_DRV=spice \
 /usr/bin/qemu -S -M pc -m 214 -smp 1 -nodefaults -monitor \
 unix:/tmp/test-monitor,server,nowait -no-acpi -boot c -hda \
 /dev/HostVG/QEMUGuest1 -usb -spice port=5903,tls-port=5904,addr=127.0.0.1,\
-x509-dir=/etc/pki/libvirt-spice,tls-channel=main,plaintext-channel=inputs -vga \
+x509-dir=/etc/pki/libvirt-spice,tls-channel=main,plaintext-channel=inputs,\
+image-compression=auto_glz,jpeg-wan-compression=auto,zlib-glz-wan-compression=auto,\
+playback-compression=on -vga \
 qxl -global qxl.vram_size=18874368 -device qxl,id=video1,vram_size=33554432,bus=pci.0,addr=0x4 \
 -device virtio-balloon-pci,id=balloon0,bus=pci.0,addr=0x3
diff --git a/tests/qemuxml2argvdata/qemuxml2argv-graphics-spice.xml b/tests/qemuxml2argvdata/qemuxml2argv-graphics-spice.xml
index 5d46509..a29f50d 100644
--- a/tests/qemuxml2argvdata/qemuxml2argv-graphics-spice.xml
+++ b/tests/qemuxml2argvdata/qemuxml2argv-graphics-spice.xml
@@ -24,6 +24,10 @@
     <graphics type='spice' port='5903' tlsPort='5904' autoport='no' listen='127.0.0.1'>
       <channel name='main' mode='secure'/>
       <channel name='inputs' mode='insecure'/>
+      <image compression='auto_glz'/>
+      <jpeg compression='auto'/>
+      <zlib compression='auto'/>
+      <playback compression='on'/>
     </graphics>
     <video>
       <model type='qxl' vram='18432' heads='1'/>
-- 
1.7.4.2


[Date Prev][Date Next]   [Thread Prev][Thread Next]   [Thread Index] [Date Index] [Author Index]