mirror of
https://gitlab.com/libvirt/libvirt.git
synced 2024-12-22 21:55:25 +00:00
Spice: support audio, 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 elements are optional.
This commit is contained in:
parent
eed9d69e3c
commit
abb1570eac
@ -1663,7 +1663,25 @@ qemu-kvm -net nic,model=? /dev/null
|
||||
<graphics type='spice' port='-1' tlsPort='-1' autoport='yes'>
|
||||
<channel name='main' mode='secure'/>
|
||||
<channel name='record' mode='insecure'/>
|
||||
<image compression='auto_glz'/>
|
||||
</graphics></pre>
|
||||
<p>
|
||||
Spice supports variable compression settings for audio,
|
||||
images and streaming, <span class="since">since
|
||||
0.9.1</span>. These settings are accessible via
|
||||
the <code>compression</code> attribute in all following
|
||||
elements: <code>image</code> to set image compression
|
||||
(accepts <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
|
||||
(accepts <code>auto</code>, <code>never</code>,
|
||||
<code>always</code>), <code>zlib</code> for configuring
|
||||
wan image compression (accepts <code>auto</code>,
|
||||
<code>never</code>, <code>always</code>)
|
||||
and <code>playback</code> for enabling audio stream
|
||||
compression (accepts <code>on</code> or <code>off</code>).
|
||||
</p>
|
||||
</dd>
|
||||
<dt><code>"rdp"</code></dt>
|
||||
<dd>
|
||||
|
@ -1260,29 +1260,81 @@
|
||||
<text/>
|
||||
</attribute>
|
||||
</optional>
|
||||
<zeroOrMore>
|
||||
<element name="channel">
|
||||
<attribute name="name">
|
||||
<choice>
|
||||
<value>main</value>
|
||||
<value>display</value>
|
||||
<value>inputs</value>
|
||||
<value>cursor</value>
|
||||
<value>playback</value>
|
||||
<value>record</value>
|
||||
<value>smartcard</value>
|
||||
</choice>
|
||||
</attribute>
|
||||
<attribute name="mode">
|
||||
<choice>
|
||||
<value>any</value>
|
||||
<value>secure</value>
|
||||
<value>insecure</value>
|
||||
</choice>
|
||||
</attribute>
|
||||
<empty/>
|
||||
</element>
|
||||
</zeroOrMore>
|
||||
<interleave>
|
||||
<zeroOrMore>
|
||||
<element name="channel">
|
||||
<attribute name="name">
|
||||
<choice>
|
||||
<value>main</value>
|
||||
<value>display</value>
|
||||
<value>inputs</value>
|
||||
<value>cursor</value>
|
||||
<value>playback</value>
|
||||
<value>record</value>
|
||||
<value>smartcard</value>
|
||||
</choice>
|
||||
</attribute>
|
||||
<attribute name="mode">
|
||||
<choice>
|
||||
<value>any</value>
|
||||
<value>secure</value>
|
||||
<value>insecure</value>
|
||||
</choice>
|
||||
</attribute>
|
||||
<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>
|
||||
</interleave>
|
||||
</group>
|
||||
<group>
|
||||
<attribute name="type">
|
||||
|
@ -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")
|
||||
@ -3955,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_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;
|
||||
@ -7818,6 +7931,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) {
|
||||
|
@ -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)
|
||||
|
@ -262,6 +262,14 @@ virDomainGraphicsSpiceChannelModeTypeFromString;
|
||||
virDomainGraphicsSpiceChannelModeTypeToString;
|
||||
virDomainGraphicsSpiceChannelNameTypeFromString;
|
||||
virDomainGraphicsSpiceChannelNameTypeToString;
|
||||
virDomainGraphicsSpiceImageCompressionTypeToString;
|
||||
virDomainGraphicsSpiceImageCompressionTypeFromString;
|
||||
virDomainGraphicsSpiceJpegCompressionTypeFromString;
|
||||
virDomainGraphicsSpiceJpegCompressionTypeToString;
|
||||
virDomainGraphicsSpicePlaybackCompressionTypeFromString;
|
||||
virDomainGraphicsSpicePlaybackCompressionTypeToString;
|
||||
virDomainGraphicsSpiceZlibCompressionTypeFromString;
|
||||
virDomainGraphicsSpiceZlibCompressionTypeToString;
|
||||
virDomainGraphicsTypeFromString;
|
||||
virDomainGraphicsTypeToString;
|
||||
virDomainHostdevDefFree;
|
||||
|
@ -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);
|
||||
|
@ -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
|
||||
|
@ -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'/>
|
||||
|
Loading…
Reference in New Issue
Block a user