From 263646a1f7e705766f7d46017679812d4b1406b8 Mon Sep 17 00:00:00 2001 From: Yonit Halperin Date: Wed, 9 Jun 2010 11:40:25 +0200 Subject: JPEG support: introducing jpeg encoding for spice bitmaps --- common/canvas_base.c | 82 +++++++++++++++++++++++++++++++++++++++++++++++++++- common/canvas_base.h | 18 ++++++++++++ common/gdi_canvas.c | 4 ++- common/gdi_canvas.h | 3 +- common/gl_canvas.c | 2 ++ common/gl_canvas.h | 1 + common/sw_canvas.c | 6 ++++ common/sw_canvas.h | 2 ++ 8 files changed, 115 insertions(+), 3 deletions(-) (limited to 'common') diff --git a/common/canvas_base.c b/common/canvas_base.c index 9d9c9772..8180f09d 100644 --- a/common/canvas_base.c +++ b/common/canvas_base.c @@ -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; diff --git a/common/canvas_base.h b/common/canvas_base.h index f78b0b8d..4eaafbbd 100644 --- a/common/canvas_base.h +++ b/common/canvas_base.h @@ -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, diff --git a/common/gdi_canvas.c b/common/gdi_canvas.c index af1de950..d01d9cde 100644 --- a/common/gdi_canvas.c +++ b/common/gdi_canvas.c @@ -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; diff --git a/common/gdi_canvas.h b/common/gdi_canvas.h index 7af0e02d..02e053d2 100644 --- a/common/gdi_canvas.h +++ b/common/gdi_canvas.h @@ -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(); diff --git a/common/gl_canvas.c b/common/gl_canvas.c index ea10c96e..f98c72a0 100644 --- a/common/gl_canvas.c +++ b/common/gl_canvas.c @@ -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 diff --git a/common/gl_canvas.h b/common/gl_canvas.h index 6dd25e92..cd76f8d9 100644 --- a/common/gl_canvas.h +++ b/common/gl_canvas.h @@ -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 diff --git a/common/sw_canvas.c b/common/sw_canvas.c index a541c7df..8280362c 100644 --- a/common/sw_canvas.c +++ b/common/sw_canvas.c @@ -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 diff --git a/common/sw_canvas.h b/common/sw_canvas.h index c3aef240..63a78630 100644 --- a/common/sw_canvas.h +++ b/common/sw_canvas.h @@ -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 -- cgit