mirror of
https://gitlab.uni-freiburg.de/opensourcevdi/spice-common
synced 2026-01-14 06:43:51 +00:00
JPEG support: introducing jpeg encoding for spice bitmaps
This commit is contained in:
parent
41171d081d
commit
19bca5b373
@ -199,6 +199,7 @@ typedef struct CanvasBase {
|
||||
|
||||
LzData lz_data;
|
||||
GlzData glz_data;
|
||||
SpiceJpegDecoder* jpeg;
|
||||
|
||||
void *usr_data;
|
||||
spice_destroy_fn_t usr_data_destroy;
|
||||
@ -547,6 +548,78 @@ static pixman_image_t *canvas_get_quic(CanvasBase *canvas, SpiceQUICImage *image
|
||||
return surface;
|
||||
}
|
||||
|
||||
|
||||
//#define DUMP_JPEG
|
||||
#ifdef DUMP_JPEG
|
||||
static int jpeg_id = 0;
|
||||
static void dump_jpeg(uint8_t* data, int data_size)
|
||||
{
|
||||
char file_str[200];
|
||||
uint32_t id = ++jpeg_id;
|
||||
|
||||
#ifdef WIN32
|
||||
sprintf(file_str, "c:\\tmp\\spice_dump\\%u.jpg", id);
|
||||
#else
|
||||
sprintf(file_str, "/tmp/spice_dump/%u.jpg", id);
|
||||
#endif
|
||||
|
||||
FILE *f = fopen(file_str, "wb");
|
||||
if (!f) {
|
||||
return;
|
||||
}
|
||||
|
||||
fwrite(data, 1, data_size, f);
|
||||
fclose(f);
|
||||
}
|
||||
#endif
|
||||
|
||||
static pixman_image_t *canvas_get_jpeg(CanvasBase *canvas, SpiceJPEGImage *image, int invers)
|
||||
{
|
||||
pixman_image_t *surface = NULL;
|
||||
int stride;
|
||||
int width;
|
||||
int height;
|
||||
uint8_t *dest;
|
||||
|
||||
canvas->jpeg->ops->begin_decode(canvas->jpeg, image->jpeg.data, image->jpeg.data_size,
|
||||
&width, &height);
|
||||
ASSERT((uint32_t)width == image->descriptor.width);
|
||||
ASSERT((uint32_t)height == image->descriptor.height);
|
||||
|
||||
surface = surface_create(
|
||||
#ifdef WIN32
|
||||
canvas->dc,
|
||||
#endif
|
||||
PIXMAN_x8r8g8b8,
|
||||
width, height, FALSE);
|
||||
if (surface == NULL) {
|
||||
CANVAS_ERROR("create surface failed");
|
||||
}
|
||||
|
||||
dest = (uint8_t *)pixman_image_get_data(surface);
|
||||
stride = pixman_image_get_stride(surface);
|
||||
|
||||
canvas->jpeg->ops->decode(canvas->jpeg, dest, stride, SPICE_BITMAP_FMT_32BIT);
|
||||
|
||||
if (invers) {
|
||||
uint8_t *end = dest + height * stride;
|
||||
for (; dest != end; dest += stride) {
|
||||
uint32_t *pix;
|
||||
uint32_t *end_pix;
|
||||
|
||||
pix = (uint32_t *)dest;
|
||||
end_pix = pix + width;
|
||||
for (; pix < end_pix; pix++) {
|
||||
*pix ^= 0x00ffffff;
|
||||
}
|
||||
}
|
||||
}
|
||||
#ifdef DUMP_JPEG
|
||||
dump_jpeg(image->jpeg.data, image->jpeg.data_size);
|
||||
#endif
|
||||
return surface;
|
||||
}
|
||||
|
||||
static pixman_image_t *canvas_bitmap_to_surface(CanvasBase *canvas, SpiceBitmap* bitmap,
|
||||
SpicePalette *palette, int want_original)
|
||||
{
|
||||
@ -1001,7 +1074,12 @@ static pixman_image_t *canvas_get_image_internal(CanvasBase *canvas, SPICE_ADDRE
|
||||
break;
|
||||
}
|
||||
#endif
|
||||
|
||||
case SPICE_IMAGE_TYPE_JPEG: {
|
||||
SpiceJPEGImage *image = (SpiceJPEGImage *)descriptor;
|
||||
access_test(canvas, descriptor, sizeof(SpiceJPEGImage));
|
||||
surface = canvas_get_jpeg(canvas, image, 0);
|
||||
break;
|
||||
}
|
||||
#if defined(SW_CANVAS_CACHE)
|
||||
case SPICE_IMAGE_TYPE_GLZ_RGB: {
|
||||
access_test(canvas, descriptor, sizeof(SpiceLZRGBImage));
|
||||
@ -3234,6 +3312,7 @@ static int canvas_base_init(CanvasBase *canvas, SpiceCanvasOps *ops,
|
||||
#endif
|
||||
, SpiceImageSurfaces *surfaces
|
||||
, SpiceGlzDecoder *glz_decoder
|
||||
, SpiceJpegDecoder *jpeg_decoder
|
||||
#ifndef SW_CANVAS_NO_CHUNKS
|
||||
, SpiceVirtMapping *virt_mapping
|
||||
#endif
|
||||
@ -3267,6 +3346,7 @@ static int canvas_base_init(CanvasBase *canvas, SpiceCanvasOps *ops,
|
||||
#endif
|
||||
canvas->surfaces = surfaces;
|
||||
canvas->glz_data.decoder = glz_decoder;
|
||||
canvas->jpeg = jpeg_decoder;
|
||||
|
||||
canvas->format = format;
|
||||
|
||||
|
||||
@ -31,6 +31,7 @@ typedef struct _SpiceImageCache SpiceImageCache;
|
||||
typedef struct _SpiceImageSurfaces SpiceImageSurfaces;
|
||||
typedef struct _SpicePaletteCache SpicePaletteCache;
|
||||
typedef struct _SpiceGlzDecoder SpiceGlzDecoder;
|
||||
typedef struct _SpiceJpegDecoder SpiceJpegDecoder;
|
||||
typedef struct _SpiceVirtMapping SpiceVirtMapping;
|
||||
typedef struct _SpiceCanvas SpiceCanvas;
|
||||
|
||||
@ -79,6 +80,23 @@ struct _SpiceGlzDecoder {
|
||||
SpiceGlzDecoderOps *ops;
|
||||
};
|
||||
|
||||
|
||||
typedef struct SpiceJpegDecoderOps {
|
||||
void (*begin_decode)(SpiceJpegDecoder *decoder,
|
||||
uint8_t* data,
|
||||
int data_size,
|
||||
int* out_width,
|
||||
int* out_height);
|
||||
void (*decode)(SpiceJpegDecoder *decoder,
|
||||
uint8_t* dest,
|
||||
int stride,
|
||||
int format);
|
||||
} SpiceJpegDecoderOps;
|
||||
|
||||
struct _SpiceJpegDecoder {
|
||||
SpiceJpegDecoderOps *ops;
|
||||
};
|
||||
|
||||
typedef struct {
|
||||
void *(*get_virt)(SpiceVirtMapping *mapping, unsigned long addr, uint32_t add_size);
|
||||
void (*validate_virt)(SpiceVirtMapping *mapping, unsigned long virt,
|
||||
|
||||
@ -1866,6 +1866,7 @@ SpiceCanvas *gdi_canvas_create(int width, int height,
|
||||
#endif
|
||||
, SpiceImageSurfaces *surfaces
|
||||
, SpiceGlzDecoder *glz_decoder
|
||||
, SpiceJpegDecoder *jpeg_decoder
|
||||
)
|
||||
{
|
||||
GdiCanvas *canvas;
|
||||
@ -1884,7 +1885,8 @@ SpiceCanvas *gdi_canvas_create(int width, int height,
|
||||
, bits_cache
|
||||
#endif
|
||||
, surfaces
|
||||
, glz_decoder);
|
||||
, glz_decoder
|
||||
, jpeg_decoder);
|
||||
canvas->dc = dc;
|
||||
canvas->lock = lock;
|
||||
return (SpiceCanvas *)canvas;
|
||||
|
||||
@ -31,7 +31,8 @@ SpiceCanvas *gdi_canvas_create(int width, int height,
|
||||
SpiceImageCache *bits_cache,
|
||||
SpicePaletteCache *palette_cache,
|
||||
SpiceImageSurfaces *surfaces,
|
||||
SpiceGlzDecoder *glz_decoder);
|
||||
SpiceGlzDecoder *glz_decoder,
|
||||
SpiceJpegDecoder *jpeg_decoder);
|
||||
|
||||
void gdi_canvas_init();
|
||||
|
||||
|
||||
@ -830,6 +830,7 @@ SpiceCanvas *gl_canvas_create(int width, int height, uint32_t format
|
||||
#endif
|
||||
, SpiceImageSurfaces *surfaces
|
||||
, SpiceGlzDecoder *glz_decoder
|
||||
, SpiceJpegDecoder *jpeg_decoder
|
||||
#ifndef SW_CANVAS_NO_CHUNKS
|
||||
, SpiceVirtMapping *virt_mapping
|
||||
#endif
|
||||
@ -857,6 +858,7 @@ SpiceCanvas *gl_canvas_create(int width, int height, uint32_t format
|
||||
#endif
|
||||
, surfaces
|
||||
, glz_decoder
|
||||
, jpeg_decoder
|
||||
#ifndef SW_CANVAS_NO_CHUNKS
|
||||
, virt_mapping
|
||||
#endif
|
||||
|
||||
@ -30,6 +30,7 @@ SpiceCanvas *gl_canvas_create(int width, int height, uint32_t format
|
||||
#endif
|
||||
, SpiceImageSurfaces *surfaces
|
||||
, SpiceGlzDecoder *glz_decoder
|
||||
, SpiceJpegDecoder *jpeg_decoder
|
||||
#ifndef SW_CANVAS_NO_CHUNKS
|
||||
, SpiceVirtMapping *virt_mapping
|
||||
#endif
|
||||
|
||||
@ -1180,6 +1180,7 @@ static SpiceCanvas *canvas_create_common(pixman_image_t *image,
|
||||
#endif
|
||||
, SpiceImageSurfaces *surfaces
|
||||
, SpiceGlzDecoder *glz_decoder
|
||||
, SpiceJpegDecoder *jpeg_decoder
|
||||
#ifndef SW_CANVAS_NO_CHUNKS
|
||||
, SpiceVirtMapping *virt_mapping
|
||||
#endif
|
||||
@ -1207,6 +1208,7 @@ static SpiceCanvas *canvas_create_common(pixman_image_t *image,
|
||||
#endif
|
||||
, surfaces
|
||||
, glz_decoder
|
||||
, jpeg_decoder
|
||||
#ifndef SW_CANVAS_NO_CHUNKS
|
||||
, virt_mapping
|
||||
#endif
|
||||
@ -1228,6 +1230,7 @@ SpiceCanvas *canvas_create(int width, int height, uint32_t format
|
||||
#endif
|
||||
, SpiceImageSurfaces *surfaces
|
||||
, SpiceGlzDecoder *glz_decoder
|
||||
, SpiceJpegDecoder *jpeg_decoder
|
||||
#ifndef SW_CANVAS_NO_CHUNKS
|
||||
, SpiceVirtMapping *virt_mapping
|
||||
#endif
|
||||
@ -1247,6 +1250,7 @@ SpiceCanvas *canvas_create(int width, int height, uint32_t format
|
||||
#endif
|
||||
, surfaces
|
||||
, glz_decoder
|
||||
, jpeg_decoder
|
||||
#ifndef SW_CANVAS_NO_CHUNKS
|
||||
, virt_mapping
|
||||
#endif
|
||||
@ -1263,6 +1267,7 @@ SpiceCanvas *canvas_create_for_data(int width, int height, uint32_t format,
|
||||
#endif
|
||||
, SpiceImageSurfaces *surfaces
|
||||
, SpiceGlzDecoder *glz_decoder
|
||||
, SpiceJpegDecoder *jpeg_decoder
|
||||
#ifndef SW_CANVAS_NO_CHUNKS
|
||||
, SpiceVirtMapping *virt_mapping
|
||||
#endif
|
||||
@ -1282,6 +1287,7 @@ SpiceCanvas *canvas_create_for_data(int width, int height, uint32_t format,
|
||||
#endif
|
||||
, surfaces
|
||||
, glz_decoder
|
||||
, jpeg_decoder
|
||||
#ifndef SW_CANVAS_NO_CHUNKS
|
||||
, virt_mapping
|
||||
#endif
|
||||
|
||||
@ -35,6 +35,7 @@ SpiceCanvas *canvas_create(int width, int height, uint32_t format
|
||||
#endif
|
||||
, SpiceImageSurfaces *surfaces
|
||||
, SpiceGlzDecoder *glz_decoder
|
||||
, SpiceJpegDecoder *jpeg_decoder
|
||||
#ifndef SW_CANVAS_NO_CHUNKS
|
||||
, SpiceVirtMapping *virt_mapping
|
||||
#endif
|
||||
@ -49,6 +50,7 @@ SpiceCanvas *canvas_create_for_data(int width, int height, uint32_t format, uint
|
||||
#endif
|
||||
, SpiceImageSurfaces *surfaces
|
||||
, SpiceGlzDecoder *glz_decoder
|
||||
, SpiceJpegDecoder *jpeg_decoder
|
||||
#ifndef SW_CANVAS_NO_CHUNKS
|
||||
, SpiceVirtMapping *virt_mapping
|
||||
#endif
|
||||
|
||||
Loading…
Reference in New Issue
Block a user