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. --- Diff to v1: - _DEFAULT in all enums - VIR_ERR_CONFIG_UNSUPPORTED if TypeFromString fails docs/formatdomain.html.in | 12 ++ docs/schemas/domain.rng | 50 ++++++++ src/conf/domain_conf.c | 125 ++++++++++++++++++++ src/conf/domain_conf.h | 46 +++++++ src/libvirt_private.syms | 8 ++ src/qemu/qemu_command.c | 12 ++ .../qemuxml2argv-graphics-spice.args | 4 +- .../qemuxml2argv-graphics-spice.xml | 4 + 8 files changed, 260 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 <channel name='main' mode='secure'/> <channel name='record' mode='insecure'/> </graphics></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..a380db3 100644 --- a/src/conf/domain_conf.c +++ b/src/conf/domain_conf.c @@ -322,6 +322,36 @@ VIR_ENUM_IMPL(virDomainGraphicsSpiceChannelMode, "secure", "insecure"); +VIR_ENUM_IMPL(virDomainGraphicsSpiceImageCompression, + VIR_DOMAIN_GRAPHICS_SPICE_IMAGE_COMPRESSION_LAST, + "default", + "auto_glz", + "auto_lz", + "quic", + "glz", + "lz", + "off"); + +VIR_ENUM_IMPL(virDomainGraphicsSpiceJpegCompression, + VIR_DOMAIN_GRAPHICS_SPICE_JPEG_COMPRESSION_LAST, + "default", + "auto", + "never", + "always"); + +VIR_ENUM_IMPL(virDomainGraphicsSpiceZlibCompression, + VIR_DOMAIN_GRAPHICS_SPICE_ZLIB_COMPRESSION_LAST, + "default", + "auto", + "never", + "always"); + +VIR_ENUM_IMPL(virDomainGraphicsSpicePlaybackCompression, + VIR_DOMAIN_GRAPHICS_SPICE_PLAYBACK_COMPRESSION_LAST, + "default", + "on", + "off"); + VIR_ENUM_IMPL(virDomainHostdevMode, VIR_DOMAIN_HOSTDEV_MODE_LAST, "subsystem", "capabilities") @@ -3954,6 +3984,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_CONFIG_UNSUPPORTED, + _("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_CONFIG_UNSUPPORTED, + _("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_CONFIG_UNSUPPORTED, + _("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_CONFIG_UNSUPPORTED, + _("unknown spice playback compression")); + VIR_FREE(compression); + goto error; + + } + VIR_FREE(compression); + + def->data.spice.playback = compressionVal; } } cur = cur->next; @@ -7817,6 +7930,18 @@ virDomainGraphicsDefFormat(virBufferPtr buf, virDomainGraphicsSpiceChannelNameTypeToString(i), virDomainGraphicsSpiceChannelModeTypeToString(mode)); } + if (def->data.spice.image) + virBufferVSprintf(buf, " <image compression='%s'/>\n", + virDomainGraphicsSpiceImageCompressionTypeToString(def->data.spice.image)); + if (def->data.spice.jpeg) + virBufferVSprintf(buf, " <jpeg compression='%s'/>\n", + virDomainGraphicsSpiceJpegCompressionTypeToString(def->data.spice.jpeg)); + if (def->data.spice.zlib) + virBufferVSprintf(buf, " <zlib compression='%s'/>\n", + virDomainGraphicsSpiceZlibCompressionTypeToString(def->data.spice.zlib)); + if (def->data.spice.playback) + 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..60a33ce 100644 --- a/src/conf/domain_conf.h +++ b/src/conf/domain_conf.h @@ -658,6 +658,44 @@ enum virDomainGraphicsSpiceChannelMode { VIR_DOMAIN_GRAPHICS_SPICE_CHANNEL_MODE_LAST }; +enum virDomainGraphicsSpiceImageCompression { + VIR_DOMAIN_GRAPHICS_SPICE_IMAGE_COMPRESSION_DEFAULT = 0, + 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_DEFAULT = 0, + 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_DEFAULT = 0, + 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_DEFAULT = 0, + 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 +733,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 +1465,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..89668d4 100644 --- a/src/qemu/qemu_command.c +++ b/src/qemu/qemu_command.c @@ -4032,6 +4032,18 @@ qemuBuildCommandLine(virConnectPtr conn, break; } } + if (def->graphics[0]->data.spice.image) + virBufferVSprintf(&opt, ",image-compression=%s", + virDomainGraphicsSpiceImageCompressionTypeToString(def->graphics[0]->data.spice.image)); + if (def->graphics[0]->data.spice.jpeg) + virBufferVSprintf(&opt, ",jpeg-wan-compression=%s", + virDomainGraphicsSpiceJpegCompressionTypeToString(def->graphics[0]->data.spice.jpeg)); + if (def->graphics[0]->data.spice.zlib) + virBufferVSprintf(&opt, ",zlib-glz-wan-compression=%s", + virDomainGraphicsSpiceZlibCompressionTypeToString(def->graphics[0]->data.spice.zlib)); + if (def->graphics[0]->data.spice.playback) + 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 -- libvir-list mailing list libvir-list@xxxxxxxxxx https://www.redhat.com/mailman/listinfo/libvir-list