mirror of
https://gitlab.uni-freiburg.de/opensourcevdi/spice
synced 2026-08-07 03:14:03 +00:00
Add LZ4 compression support.
- Add lz4 encoder to compress an image of type LZ4 (see spice_common). - Add code in red_worker to use LZ4 when it is enabled, and the client supports it through its display capability, or fallback to LZ. - Add enable_lz4 switch in the configure script. Show LZ4 support at the end.
This commit is contained in:
parent
84b3a5079d
commit
b532ef0866
15
configure.ac
15
configure.ac
@ -138,6 +138,12 @@ AC_ARG_ENABLE(opengl,
|
||||
AS_IF([test x"$enable_opengl" != "xno"], [enable_opengl="yes"])
|
||||
AM_CONDITIONAL(SUPPORT_GL, test "x$enable_opengl" = "xyes")
|
||||
|
||||
AC_ARG_ENABLE(lz4,
|
||||
[ --enable-lz4 Enable lz4 compression algorithm],,
|
||||
[enable_lz4="no"])
|
||||
AS_IF([test x"$enable_lz4" != "xno"], [enable_lz4="yes"])
|
||||
AM_CONDITIONAL(SUPPORT_LZ4, test "x$enable_lz4" = "xyes")
|
||||
|
||||
AC_ARG_ENABLE(smartcard,
|
||||
[ --enable-smartcard Enable network redirection],,
|
||||
[enable_smartcard="no"])
|
||||
@ -287,6 +293,13 @@ AC_ARG_ENABLE([xinerama],
|
||||
[AS_HELP_STRING([--disable-xinerama],
|
||||
[disable Xinerama library @<:@default=no@:>@])])
|
||||
|
||||
if test "x$enable_lz4" = "xyes"; then
|
||||
PKG_CHECK_MODULES(LZ4, liblz4)
|
||||
AC_DEFINE([USE_LZ4], [1], [Define to build with Lz4 support])
|
||||
fi
|
||||
AC_SUBST(LZ4_CFLAGS)
|
||||
AC_SUBST(LZ4_LIBS)
|
||||
|
||||
if test "x$red_target" = "xx11" && test "x$enable_client" = "xyes" ; then
|
||||
if test "$os_linux" = yes; then
|
||||
PKG_CHECK_MODULES(ALSA, alsa)
|
||||
@ -549,6 +562,8 @@ echo "
|
||||
|
||||
GUI: ${enable_gui}
|
||||
" ; fi ; echo "\
|
||||
LZ4 support: ${enable_lz4}
|
||||
|
||||
Smartcard: ${enable_smartcard}
|
||||
|
||||
SASL support: ${enable_sasl}
|
||||
|
||||
@ -6,6 +6,7 @@ AM_CPPFLAGS = \
|
||||
-DRED_STATISTICS \
|
||||
$(COMMON_CFLAGS) \
|
||||
$(GLIB2_CFLAGS) \
|
||||
$(LZ4_CFLAGS) \
|
||||
$(PIXMAN_CFLAGS) \
|
||||
$(SASL_CFLAGS) \
|
||||
$(SLIRP_CFLAGS) \
|
||||
@ -35,6 +36,7 @@ libspice_server_la_LIBADD = \
|
||||
$(GL_LIBS) \
|
||||
$(GLIB2_LIBS) \
|
||||
$(JPEG_LIBS) \
|
||||
$(LZ4_LIBS) \
|
||||
$(LIBRT) \
|
||||
$(PIXMAN_LIBS) \
|
||||
$(SASL_LIBS) \
|
||||
@ -75,6 +77,8 @@ libspice_server_la_SOURCES = \
|
||||
inputs_channel.h \
|
||||
jpeg_encoder.c \
|
||||
jpeg_encoder.h \
|
||||
lz4_encoder.c \
|
||||
lz4_encoder.h \
|
||||
main_channel.c \
|
||||
main_channel.h \
|
||||
mjpeg_encoder.c \
|
||||
|
||||
122
server/lz4_encoder.c
Normal file
122
server/lz4_encoder.c
Normal file
@ -0,0 +1,122 @@
|
||||
/*
|
||||
Copyright (C) 2014 Flexible Software Solutions S.L.
|
||||
|
||||
This library is free software; you can redistribute it and/or
|
||||
modify it under the terms of the GNU Lesser General Public
|
||||
License as published by the Free Software Foundation; either
|
||||
version 2.1 of the License, or (at your option) any later version.
|
||||
|
||||
This library is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
Lesser General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU Lesser General Public
|
||||
License along with this library; if not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
#ifdef HAVE_CONFIG_H
|
||||
#include <config.h>
|
||||
#endif
|
||||
|
||||
#ifdef USE_LZ4
|
||||
|
||||
#define SPICE_LOG_DOMAIN "SpiceLz4Encoder"
|
||||
|
||||
#include <arpa/inet.h>
|
||||
#include <lz4.h>
|
||||
#include "red_common.h"
|
||||
#include "lz4_encoder.h"
|
||||
|
||||
typedef struct Lz4Encoder {
|
||||
Lz4EncoderUsrContext *usr;
|
||||
} Lz4Encoder;
|
||||
|
||||
Lz4EncoderContext* lz4_encoder_create(Lz4EncoderUsrContext *usr)
|
||||
{
|
||||
Lz4Encoder *enc;
|
||||
if (!usr->more_space || !usr->more_lines) {
|
||||
return NULL;
|
||||
}
|
||||
|
||||
enc = spice_new0(Lz4Encoder, 1);
|
||||
enc->usr = usr;
|
||||
|
||||
return (Lz4EncoderContext*)enc;
|
||||
}
|
||||
|
||||
void lz4_encoder_destroy(Lz4EncoderContext* encoder)
|
||||
{
|
||||
free(encoder);
|
||||
}
|
||||
|
||||
int lz4_encode(Lz4EncoderContext *lz4, int height, int stride,
|
||||
uint8_t *io_ptr, unsigned int num_io_bytes)
|
||||
{
|
||||
Lz4Encoder *enc = (Lz4Encoder *)lz4;
|
||||
uint8_t *lines;
|
||||
int num_lines = 0;
|
||||
int total_lines = 0;
|
||||
int in_size, enc_size, out_size = 0, already_copied;
|
||||
int stride_abs = abs(stride);
|
||||
uint8_t *in_buf, *compressed_lines;
|
||||
uint8_t *out_buf = io_ptr;
|
||||
LZ4_stream_t *stream = LZ4_createStream();
|
||||
|
||||
// Encode direction
|
||||
*(out_buf++) = stride < 0 ? 1 : 0;
|
||||
num_io_bytes--;
|
||||
|
||||
do {
|
||||
num_lines = enc->usr->more_lines(enc->usr, &lines);
|
||||
if (num_lines <= 0) {
|
||||
spice_error("more lines failed");
|
||||
LZ4_freeStream(stream);
|
||||
return 0;
|
||||
}
|
||||
in_buf = stride < 0 ? lines - (stride_abs * (num_lines - 1)) : lines;
|
||||
lines += stride * num_lines;
|
||||
in_size = stride_abs * num_lines;
|
||||
compressed_lines = (uint8_t *) malloc(LZ4_compressBound(in_size) + 4);
|
||||
enc_size = LZ4_compress_continue(stream, (const char *) in_buf,
|
||||
(char *) compressed_lines + 4, in_size);
|
||||
if (enc_size <= 0) {
|
||||
spice_error("compress failed!");
|
||||
free(compressed_lines);
|
||||
LZ4_freeStream(stream);
|
||||
return 0;
|
||||
}
|
||||
*((uint32_t *)compressed_lines) = htonl(enc_size);
|
||||
|
||||
out_size += enc_size += 4;
|
||||
already_copied = 0;
|
||||
while (num_io_bytes < enc_size) {
|
||||
memcpy(out_buf, compressed_lines + already_copied, num_io_bytes);
|
||||
already_copied += num_io_bytes;
|
||||
enc_size -= num_io_bytes;
|
||||
num_io_bytes = enc->usr->more_space(enc->usr, &io_ptr);
|
||||
if (num_io_bytes <= 0) {
|
||||
spice_error("more space failed");
|
||||
free(compressed_lines);
|
||||
LZ4_freeStream(stream);
|
||||
return 0;
|
||||
}
|
||||
out_buf = io_ptr;
|
||||
}
|
||||
memcpy(out_buf, compressed_lines + already_copied, enc_size);
|
||||
out_buf += enc_size;
|
||||
num_io_bytes -= enc_size;
|
||||
|
||||
free(compressed_lines);
|
||||
total_lines += num_lines;
|
||||
} while (total_lines < height);
|
||||
|
||||
LZ4_freeStream(stream);
|
||||
if (total_lines != height) {
|
||||
spice_error("too many lines\n");
|
||||
out_size = 0;
|
||||
}
|
||||
|
||||
return out_size;
|
||||
}
|
||||
|
||||
#endif // USE_LZ4
|
||||
50
server/lz4_encoder.h
Normal file
50
server/lz4_encoder.h
Normal file
@ -0,0 +1,50 @@
|
||||
/*
|
||||
Copyright (C) 2014 Flexible Software Solutions S.L.
|
||||
|
||||
Redistribution and use in source and binary forms, with or without
|
||||
modification, are permitted provided that the following conditions are
|
||||
met:
|
||||
|
||||
* Redistributions of source code must retain the above copyright
|
||||
notice, this list of conditions and the following disclaimer.
|
||||
* Redistributions in binary form must reproduce the above copyright
|
||||
notice, this list of conditions and the following disclaimer in
|
||||
the documentation and/or other materials provided with the
|
||||
distribution.
|
||||
* Neither the name of the copyright holder nor the names of its
|
||||
contributors may be used to endorse or promote products derived
|
||||
from this software without specific prior written permission.
|
||||
|
||||
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDER AND CONTRIBUTORS "AS
|
||||
IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
|
||||
TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A
|
||||
PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
|
||||
HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
|
||||
SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
|
||||
LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
||||
DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
|
||||
THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
||||
OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
#ifndef _H_LZ4_ENCODER
|
||||
#define _H_LZ4_ENCODER
|
||||
|
||||
#include <spice/types.h>
|
||||
|
||||
typedef void* Lz4EncoderContext;
|
||||
typedef struct Lz4EncoderUsrContext Lz4EncoderUsrContext;
|
||||
|
||||
struct Lz4EncoderUsrContext {
|
||||
int (*more_space)(Lz4EncoderUsrContext *usr, uint8_t **io_ptr);
|
||||
int (*more_lines)(Lz4EncoderUsrContext *usr, uint8_t **lines);
|
||||
};
|
||||
|
||||
Lz4EncoderContext* lz4_encoder_create(Lz4EncoderUsrContext *usr);
|
||||
void lz4_encoder_destroy(Lz4EncoderContext *encoder);
|
||||
|
||||
/* returns the total size of the encoded data. Images must be supplied from the
|
||||
top line to the bottom */
|
||||
int lz4_encode(Lz4EncoderContext *lz4, int height, int stride,
|
||||
uint8_t *io_ptr, unsigned int num_io_bytes);
|
||||
#endif
|
||||
@ -74,6 +74,9 @@
|
||||
#include "red_memslots.h"
|
||||
#include "red_parse_qxl.h"
|
||||
#include "jpeg_encoder.h"
|
||||
#ifdef USE_LZ4
|
||||
#include "lz4_encoder.h"
|
||||
#endif
|
||||
#include "demarshallers.h"
|
||||
#include "zlib_encoder.h"
|
||||
#include "red_channel.h"
|
||||
@ -237,6 +240,7 @@ static const char *quic_stat_name = "quic";
|
||||
static const char *jpeg_stat_name = "jpeg";
|
||||
static const char *zlib_stat_name = "zlib_glz";
|
||||
static const char *jpeg_alpha_stat_name = "jpeg_alpha";
|
||||
static const char *lz4_stat_name = "lz4";
|
||||
|
||||
static inline void stat_compress_init(stat_info_t *info, const char *name)
|
||||
{
|
||||
@ -599,6 +603,13 @@ typedef struct {
|
||||
EncoderData data;
|
||||
} JpegData;
|
||||
|
||||
#ifdef USE_LZ4
|
||||
typedef struct {
|
||||
Lz4EncoderUsrContext usr;
|
||||
EncoderData data;
|
||||
} Lz4Data;
|
||||
#endif
|
||||
|
||||
typedef struct {
|
||||
ZlibEncoderUsrContext usr;
|
||||
EncoderData data;
|
||||
@ -740,6 +751,7 @@ struct DisplayChannel {
|
||||
stat_info_t jpeg_stat;
|
||||
stat_info_t zlib_glz_stat;
|
||||
stat_info_t jpeg_alpha_stat;
|
||||
stat_info_t lz4_stat;
|
||||
#endif
|
||||
};
|
||||
|
||||
@ -998,6 +1010,11 @@ typedef struct RedWorker {
|
||||
JpegData jpeg_data;
|
||||
JpegEncoderContext *jpeg;
|
||||
|
||||
#ifdef USE_LZ4
|
||||
Lz4Data lz4_data;
|
||||
Lz4EncoderContext *lz4;
|
||||
#endif
|
||||
|
||||
ZlibData zlib_data;
|
||||
ZlibEncoder *zlib;
|
||||
|
||||
@ -1190,27 +1207,37 @@ static void print_compress_stats(DisplayChannel *display_channel)
|
||||
stat_byte_to_mega(display_channel->jpeg_alpha_stat.comp_size),
|
||||
stat_cpu_time_to_sec(display_channel->jpeg_alpha_stat.total)
|
||||
);
|
||||
spice_info("LZ4 \t%8d\t%13.2f\t%12.2f\t%12.2f",
|
||||
display_channel->lz4_stat.count,
|
||||
stat_byte_to_mega(display_channel->lz4_stat.orig_size),
|
||||
stat_byte_to_mega(display_channel->lz4_stat.comp_size),
|
||||
stat_cpu_time_to_sec(display_channel->lz4_stat.total)
|
||||
);
|
||||
spice_info("-------------------------------------------------------------------");
|
||||
spice_info("Total \t%8d\t%13.2f\t%12.2f\t%12.2f",
|
||||
display_channel->lz_stat.count + display_channel->glz_stat.count +
|
||||
display_channel->quic_stat.count +
|
||||
display_channel->jpeg_stat.count +
|
||||
display_channel->lz4_stat.count +
|
||||
display_channel->jpeg_alpha_stat.count,
|
||||
stat_byte_to_mega(display_channel->lz_stat.orig_size +
|
||||
display_channel->glz_stat.orig_size +
|
||||
display_channel->quic_stat.orig_size +
|
||||
display_channel->jpeg_stat.orig_size +
|
||||
display_channel->lz4_stat.orig_size +
|
||||
display_channel->jpeg_alpha_stat.orig_size),
|
||||
stat_byte_to_mega(display_channel->lz_stat.comp_size +
|
||||
glz_enc_size +
|
||||
display_channel->quic_stat.comp_size +
|
||||
display_channel->jpeg_stat.comp_size +
|
||||
display_channel->lz4_stat.comp_size +
|
||||
display_channel->jpeg_alpha_stat.comp_size),
|
||||
stat_cpu_time_to_sec(display_channel->lz_stat.total +
|
||||
display_channel->glz_stat.total +
|
||||
display_channel->zlib_glz_stat.total +
|
||||
display_channel->quic_stat.total +
|
||||
display_channel->jpeg_stat.total +
|
||||
display_channel->lz4_stat.total +
|
||||
display_channel->jpeg_alpha_stat.total)
|
||||
);
|
||||
}
|
||||
@ -5725,6 +5752,14 @@ static int jpeg_usr_more_space(JpegEncoderUsrContext *usr, uint8_t **io_ptr)
|
||||
return (encoder_usr_more_space(usr_data, (uint32_t **)io_ptr) << 2);
|
||||
}
|
||||
|
||||
#ifdef USE_LZ4
|
||||
static int lz4_usr_more_space(Lz4EncoderUsrContext *usr, uint8_t **io_ptr)
|
||||
{
|
||||
EncoderData *usr_data = &(((Lz4Data *)usr)->data);
|
||||
return (encoder_usr_more_space(usr_data, (uint32_t **)io_ptr) << 2);
|
||||
}
|
||||
#endif
|
||||
|
||||
static int zlib_usr_more_space(ZlibEncoderUsrContext *usr, uint8_t **io_ptr)
|
||||
{
|
||||
EncoderData *usr_data = &(((ZlibData *)usr)->data);
|
||||
@ -5785,6 +5820,14 @@ static int jpeg_usr_more_lines(JpegEncoderUsrContext *usr, uint8_t **lines)
|
||||
return encoder_usr_more_lines(usr_data, lines);
|
||||
}
|
||||
|
||||
#ifdef USE_LZ4
|
||||
static int lz4_usr_more_lines(Lz4EncoderUsrContext *usr, uint8_t **lines)
|
||||
{
|
||||
EncoderData *usr_data = &(((Lz4Data *)usr)->data);
|
||||
return encoder_usr_more_lines(usr_data, lines);
|
||||
}
|
||||
#endif
|
||||
|
||||
static int zlib_usr_more_input(ZlibEncoderUsrContext *usr, uint8_t** input)
|
||||
{
|
||||
EncoderData *usr_data = &(((ZlibData *)usr)->data);
|
||||
@ -5886,6 +5929,20 @@ static inline void red_init_jpeg(RedWorker *worker)
|
||||
}
|
||||
}
|
||||
|
||||
#ifdef USE_LZ4
|
||||
static inline void red_init_lz4(RedWorker *worker)
|
||||
{
|
||||
worker->lz4_data.usr.more_space = lz4_usr_more_space;
|
||||
worker->lz4_data.usr.more_lines = lz4_usr_more_lines;
|
||||
|
||||
worker->lz4 = lz4_encoder_create(&worker->lz4_data.usr);
|
||||
|
||||
if (!worker->lz4) {
|
||||
spice_critical("create lz4 encoder failed");
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
static inline void red_init_zlib(RedWorker *worker)
|
||||
{
|
||||
worker->zlib_data.usr.more_space = zlib_usr_more_space;
|
||||
@ -6355,6 +6412,80 @@ static int red_jpeg_compress_image(DisplayChannelClient *dcc, SpiceImage *dest,
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
#ifdef USE_LZ4
|
||||
static int red_lz4_compress_image(DisplayChannelClient *dcc, SpiceImage *dest,
|
||||
SpiceBitmap *src, compress_send_data_t* o_comp_data,
|
||||
uint32_t group_id)
|
||||
{
|
||||
DisplayChannel *display_channel = DCC_TO_DC(dcc);
|
||||
RedWorker *worker = display_channel->common.worker;
|
||||
Lz4Data *lz4_data = &worker->lz4_data;
|
||||
Lz4EncoderContext *lz4 = worker->lz4;
|
||||
int lz4_size = 0;
|
||||
int stride;
|
||||
|
||||
#ifdef COMPRESS_STAT
|
||||
stat_time_t start_time = stat_now();
|
||||
#endif
|
||||
|
||||
lz4_data->data.bufs_tail = red_display_alloc_compress_buf(dcc);
|
||||
lz4_data->data.bufs_head = lz4_data->data.bufs_tail;
|
||||
|
||||
if (!lz4_data->data.bufs_head) {
|
||||
spice_warning("failed to allocate compress buffer");
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
lz4_data->data.bufs_head->send_next = NULL;
|
||||
lz4_data->data.dcc = dcc;
|
||||
|
||||
if (setjmp(lz4_data->data.jmp_env)) {
|
||||
while (lz4_data->data.bufs_head) {
|
||||
RedCompressBuf *buf = lz4_data->data.bufs_head;
|
||||
lz4_data->data.bufs_head = buf->send_next;
|
||||
red_display_free_compress_buf(dcc, buf);
|
||||
}
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
if (src->data->flags & SPICE_CHUNKS_FLAGS_UNSTABLE) {
|
||||
spice_chunks_linearize(src->data);
|
||||
}
|
||||
|
||||
lz4_data->data.u.lines_data.chunks = src->data;
|
||||
lz4_data->data.u.lines_data.stride = src->stride;
|
||||
lz4_data->usr.more_lines = lz4_usr_more_lines;
|
||||
|
||||
if ((src->flags & SPICE_BITMAP_FLAGS_TOP_DOWN)) {
|
||||
lz4_data->data.u.lines_data.next = 0;
|
||||
lz4_data->data.u.lines_data.reverse = 0;
|
||||
stride = src->stride;
|
||||
} else {
|
||||
lz4_data->data.u.lines_data.next = src->data->num_chunks - 1;
|
||||
lz4_data->data.u.lines_data.reverse = 1;
|
||||
stride = -src->stride;
|
||||
}
|
||||
|
||||
lz4_size = lz4_encode(lz4, src->y, stride, (uint8_t*)lz4_data->data.bufs_head->buf,
|
||||
sizeof(lz4_data->data.bufs_head->buf));
|
||||
|
||||
// the compressed buffer is bigger than the original data
|
||||
if (lz4_size > (src->y * src->stride)) {
|
||||
longjmp(lz4_data->data.jmp_env, 1);
|
||||
}
|
||||
|
||||
dest->descriptor.type = SPICE_IMAGE_TYPE_LZ4;
|
||||
dest->u.lz4.data_size = lz4_size;
|
||||
|
||||
o_comp_data->comp_buf = lz4_data->data.bufs_head;
|
||||
o_comp_data->comp_buf_size = lz4_size;
|
||||
|
||||
stat_compress_add(&display_channel->lz4_stat, start_time, src->stride * src->y,
|
||||
o_comp_data->comp_buf_size);
|
||||
return TRUE;
|
||||
}
|
||||
#endif
|
||||
|
||||
static inline int red_quic_compress_image(DisplayChannelClient *dcc, SpiceImage *dest,
|
||||
SpiceBitmap *src, compress_send_data_t* o_comp_data,
|
||||
uint32_t group_id)
|
||||
@ -6471,6 +6602,7 @@ static inline int red_compress_image(DisplayChannelClient *dcc,
|
||||
if (_stride_is_extra(src) || (src->data->flags & SPICE_CHUNKS_FLAGS_UNSTABLE)) {
|
||||
if ((image_compression == SPICE_IMAGE_COMPRESS_LZ) ||
|
||||
(image_compression == SPICE_IMAGE_COMPRESS_GLZ) ||
|
||||
(image_compression == SPICE_IMAGE_COMPRESS_LZ4) ||
|
||||
BITMAP_FMT_IS_PLT[src->format]) {
|
||||
return FALSE;
|
||||
} else {
|
||||
@ -6522,7 +6654,8 @@ static inline int red_compress_image(DisplayChannelClient *dcc,
|
||||
(src->x * src->y) < glz_enc_dictionary_get_size(
|
||||
dcc->glz_dict->dict));
|
||||
} else if ((image_compression == SPICE_IMAGE_COMPRESS_AUTO_LZ) ||
|
||||
(image_compression == SPICE_IMAGE_COMPRESS_LZ)) {
|
||||
(image_compression == SPICE_IMAGE_COMPRESS_LZ) ||
|
||||
(image_compression == SPICE_IMAGE_COMPRESS_LZ4)) {
|
||||
glz = FALSE;
|
||||
} else {
|
||||
spice_error("invalid image compression type %u", image_compression);
|
||||
@ -6543,8 +6676,16 @@ static inline int red_compress_image(DisplayChannelClient *dcc,
|
||||
}
|
||||
|
||||
if (!glz) {
|
||||
ret = red_lz_compress_image(dcc, dest, src, o_comp_data,
|
||||
drawable->group_id);
|
||||
#ifdef USE_LZ4
|
||||
if (image_compression == SPICE_IMAGE_COMPRESS_LZ4 &&
|
||||
red_channel_client_test_remote_cap(&dcc->common.base,
|
||||
SPICE_DISPLAY_CAP_LZ4_COMPRESSION)) {
|
||||
ret = red_lz4_compress_image(dcc, dest, src, o_comp_data,
|
||||
drawable->group_id);
|
||||
} else
|
||||
#endif
|
||||
ret = red_lz_compress_image(dcc, dest, src, o_comp_data,
|
||||
drawable->group_id);
|
||||
#ifdef COMPRESS_DEBUG
|
||||
spice_info("LZ LOCAL compress");
|
||||
#endif
|
||||
@ -8775,9 +8916,18 @@ static void red_marshall_image(RedChannelClient *rcc, SpiceMarshaller *m, ImageI
|
||||
&comp_send_data,
|
||||
worker->mem_slots.internal_groupslot_id);
|
||||
} else {
|
||||
comp_succeeded = red_lz_compress_image(dcc, &red_image, &bitmap,
|
||||
&comp_send_data,
|
||||
worker->mem_slots.internal_groupslot_id);
|
||||
#ifdef USE_LZ4
|
||||
if (comp_mode == SPICE_IMAGE_COMPRESS_LZ4 &&
|
||||
red_channel_client_test_remote_cap(&dcc->common.base,
|
||||
SPICE_DISPLAY_CAP_LZ4_COMPRESSION)) {
|
||||
comp_succeeded = red_lz4_compress_image(dcc, &red_image, &bitmap,
|
||||
&comp_send_data,
|
||||
worker->mem_slots.internal_groupslot_id);
|
||||
} else
|
||||
#endif
|
||||
comp_succeeded = red_lz_compress_image(dcc, &red_image, &bitmap,
|
||||
&comp_send_data,
|
||||
worker->mem_slots.internal_groupslot_id);
|
||||
}
|
||||
}
|
||||
|
||||
@ -10567,6 +10717,7 @@ static void display_channel_create(RedWorker *worker, int migrate)
|
||||
stat_compress_init(&display_channel->jpeg_stat, jpeg_stat_name);
|
||||
stat_compress_init(&display_channel->zlib_glz_stat, zlib_stat_name);
|
||||
stat_compress_init(&display_channel->jpeg_alpha_stat, jpeg_alpha_stat_name);
|
||||
stat_compress_init(&display_channel->lz4_stat, lz4_stat_name);
|
||||
}
|
||||
|
||||
static void guest_set_client_capabilities(RedWorker *worker)
|
||||
@ -11591,6 +11742,11 @@ void handle_dev_set_compression(void *opaque, void *payload)
|
||||
case SPICE_IMAGE_COMPRESS_QUIC:
|
||||
spice_info("ic quic");
|
||||
break;
|
||||
#ifdef USE_LZ4
|
||||
case SPICE_IMAGE_COMPRESS_LZ4:
|
||||
spice_info("ic lz4");
|
||||
break;
|
||||
#endif
|
||||
case SPICE_IMAGE_COMPRESS_LZ:
|
||||
spice_info("ic lz");
|
||||
break;
|
||||
@ -11612,6 +11768,7 @@ void handle_dev_set_compression(void *opaque, void *payload)
|
||||
stat_reset(&worker->display_channel->jpeg_stat);
|
||||
stat_reset(&worker->display_channel->zlib_glz_stat);
|
||||
stat_reset(&worker->display_channel->jpeg_alpha_stat);
|
||||
stat_reset(&worker->display_channel->lz4_stat);
|
||||
}
|
||||
#endif
|
||||
}
|
||||
@ -12015,6 +12172,9 @@ SPICE_GNUC_NORETURN void *red_worker_main(void *arg)
|
||||
red_init_quic(worker);
|
||||
red_init_lz(worker);
|
||||
red_init_jpeg(worker);
|
||||
#ifdef USE_LZ4
|
||||
red_init_lz4(worker);
|
||||
#endif
|
||||
red_init_zlib(worker);
|
||||
worker->event_timeout = INF_EVENT_WAIT;
|
||||
for (;;) {
|
||||
|
||||
@ -74,6 +74,7 @@ typedef enum {
|
||||
SPICE_IMAGE_COMPRESS_QUIC = 4,
|
||||
SPICE_IMAGE_COMPRESS_GLZ = 5,
|
||||
SPICE_IMAGE_COMPRESS_LZ = 6,
|
||||
SPICE_IMAGE_COMPRESS_LZ4 = 7,
|
||||
} spice_image_compression_t;
|
||||
|
||||
int spice_server_set_image_compression(SpiceServer *s,
|
||||
|
||||
@ -1 +1 @@
|
||||
Subproject commit b3a00f4411962e0c06c7ad89a9936df388aa0023
|
||||
Subproject commit 5b3cdad921d32c9294377efac61243a09f849d08
|
||||
Loading…
Reference in New Issue
Block a user