From 3fa2c4830ef54047228f7910b32bb3c7bab00a6a Mon Sep 17 00:00:00 2001 From: Vic Lee Date: Mon, 5 Mar 2012 17:32:14 +0800 Subject: [PATCH] nsc: refactor nsc decoder #1 o the decoded argb buffer can be reused to enhance performance o pass width, height and bpp through nsc_process_message() call o rename nsc_context_destroy to nsc_context_free and make it actually free the context --- client/Windows/wf_gdi.c | 6 ++--- client/X11/xf_gdi.c | 6 ++--- client/X11/xfreerdp.c | 6 +++++ include/freerdp/codec/nsc.h | 9 +++---- libfreerdp-codec/nsc.c | 48 +++++++++++++++++++++++++++---------- libfreerdp-gdi/gdi.c | 6 ++--- 6 files changed, 53 insertions(+), 28 deletions(-) diff --git a/client/Windows/wf_gdi.c b/client/Windows/wf_gdi.c index 9943c37b9..50dec04a7 100644 --- a/client/Windows/wf_gdi.c +++ b/client/Windows/wf_gdi.c @@ -457,16 +457,14 @@ void wf_gdi_surface_bits(rdpContext* context, SURFACE_BITS_COMMAND* surface_bits } else if (surface_bits_command->codecID == CODEC_ID_NSCODEC) { - nsc_context->width = surface_bits_command->width; - nsc_context->height = surface_bits_command->height; - nsc_process_message(nsc_context, surface_bits_command->bitmapData, surface_bits_command->bitmapDataLength); + nsc_process_message(nsc_context, surface_bits_command->bpp, surface_bits_command->width, surface_bits_command->height, + surface_bits_command->bitmapData, surface_bits_command->bitmapDataLength); wfi->image->_bitmap.width = surface_bits_command->width; wfi->image->_bitmap.height = surface_bits_command->height; wfi->image->_bitmap.bpp = surface_bits_command->bpp; wfi->image->_bitmap.data = (uint8*) xrealloc(wfi->image->_bitmap.data, wfi->image->_bitmap.width * wfi->image->_bitmap.height * 4); freerdp_image_flip(nsc_context->bmpdata, wfi->image->_bitmap.data, wfi->image->_bitmap.width, wfi->image->_bitmap.height, 32); BitBlt(wfi->primary->hdc, surface_bits_command->destLeft, surface_bits_command->destTop, surface_bits_command->width, surface_bits_command->height, wfi->image->hdc, 0, 0, GDI_SRCCOPY); - nsc_context_destroy(nsc_context); } else if (surface_bits_command->codecID == CODEC_ID_NONE) { diff --git a/client/X11/xf_gdi.c b/client/X11/xf_gdi.c index bf1395166..89a0a764c 100644 --- a/client/X11/xf_gdi.c +++ b/client/X11/xf_gdi.c @@ -928,9 +928,8 @@ void xf_gdi_surface_bits(rdpContext* context, SURFACE_BITS_COMMAND* surface_bits } else if (surface_bits_command->codecID == CODEC_ID_NSCODEC) { - nsc_context->width = surface_bits_command->width; - nsc_context->height = surface_bits_command->height; - nsc_process_message(nsc_context, surface_bits_command->bitmapData, surface_bits_command->bitmapDataLength); + nsc_process_message(nsc_context, surface_bits_command->bpp, surface_bits_command->width, surface_bits_command->height, + surface_bits_command->bitmapData, surface_bits_command->bitmapDataLength); XSetFunction(xfi->display, xfi->gc, GXcopy); XSetFillStyle(xfi->display, xfi->gc, FillSolid); @@ -959,7 +958,6 @@ void xf_gdi_surface_bits(rdpContext* context, SURFACE_BITS_COMMAND* surface_bits surface_bits_command->width, surface_bits_command->height); XSetClipMask(xfi->display, xfi->gc, None); - nsc_context_destroy(nsc_context); } else if (surface_bits_command->codecID == CODEC_ID_NONE) { diff --git a/client/X11/xfreerdp.c b/client/X11/xfreerdp.c index 127e9a4ef..5247a2d44 100644 --- a/client/X11/xfreerdp.c +++ b/client/X11/xfreerdp.c @@ -1003,6 +1003,12 @@ void xf_window_free(xfInfo* xfi) xfi->rfx_context = NULL; } + if (xfi->nsc_context) + { + nsc_context_free(xfi->nsc_context); + xfi->nsc_context = NULL; + } + freerdp_clrconv_free(xfi->clrconv); if (xfi->hdc) diff --git a/include/freerdp/codec/nsc.h b/include/freerdp/codec/nsc.h index 73e448a7d..8f075dc8c 100644 --- a/include/freerdp/codec/nsc.h +++ b/include/freerdp/codec/nsc.h @@ -46,17 +46,18 @@ struct _NSC_CONTEXT { uint32 OrgByteCount[4]; /* original byte length of luma, chroma orange, chroma green, alpha variable in order */ NSC_STREAM* nsc_stream; + uint16 bpp; uint16 width; uint16 height; uint8* bmpdata; /* final argb values in little endian order */ + uint32 bmpdata_length; /* the maximum length of the buffer that bmpdata points to */ STREAM* org_buf[4]; /* Decompressed Plane Buffers in the respective order */ }; typedef struct _NSC_CONTEXT NSC_CONTEXT; FREERDP_API NSC_CONTEXT* nsc_context_new(void); -FREERDP_API void nsc_process_message(NSC_CONTEXT* context, uint8* data, uint32 length); -FREERDP_API void nsc_context_initialize(NSC_CONTEXT* context, STREAM* s); -FREERDP_API void nsc_stream_initialize(NSC_CONTEXT* context, STREAM* s); +FREERDP_API void nsc_process_message(NSC_CONTEXT* context, uint16 bpp, + uint16 width, uint16 height, uint8* data, uint32 length); FREERDP_API void nsc_rle_decompress_data(NSC_CONTEXT* context); FREERDP_API void nsc_ycocg_rgb_convert(NSC_CONTEXT* context); FREERDP_API void nsc_rle_decode(STREAM* in, STREAM* out, uint32 origsz); @@ -64,7 +65,7 @@ FREERDP_API void nsc_chroma_supersample(NSC_CONTEXT* context); FREERDP_API void nsc_cl_expand(STREAM* stream, uint8 shiftcount, uint32 origsz); FREERDP_API void nsc_colorloss_recover(NSC_CONTEXT* context); FREERDP_API void nsc_ycocg_rgb(NSC_CONTEXT* context); -FREERDP_API void nsc_context_destroy(NSC_CONTEXT* context); +FREERDP_API void nsc_context_free(NSC_CONTEXT* context); #ifdef __cplusplus } diff --git a/libfreerdp-codec/nsc.c b/libfreerdp-codec/nsc.c index a39bdd33e..287d34141 100644 --- a/libfreerdp-codec/nsc.c +++ b/libfreerdp-codec/nsc.c @@ -289,7 +289,7 @@ void nsc_combine_argb(NSC_CONTEXT* context) } } -void nsc_stream_initialize(NSC_CONTEXT* context, STREAM* s) +static void nsc_stream_initialize(NSC_CONTEXT* context, STREAM* s) { int i; @@ -300,16 +300,29 @@ void nsc_stream_initialize(NSC_CONTEXT* context, STREAM* s) stream_read_uint8(s, context->nsc_stream->ChromaSubSamplingLevel); stream_seek(s, 2); - context->nsc_stream->pdata = stream_new(0); + if (context->nsc_stream->pdata == NULL) + context->nsc_stream->pdata = stream_new(0); stream_attach(context->nsc_stream->pdata, s->p, BYTESUM(context->nsc_stream->PlaneByteCount)); } -void nsc_context_initialize(NSC_CONTEXT* context, STREAM* s) +static void nsc_context_initialize(NSC_CONTEXT* context, STREAM* s) { int i; + uint32 length; uint32 tempsz; + nsc_stream_initialize(context, s); - context->bmpdata = xzalloc(context->width * context->height * 4); + length = context->width * context->height * 4; + if (context->bmpdata == NULL) + { + context->bmpdata = xzalloc(length); + context->bmpdata_length = length; + } + else if (length > context->bmpdata_length) + { + context->bmpdata = xrealloc(context->bmpdata, length); + context->bmpdata_length = length; + } for (i = 0; i < 4; i++) context->OrgByteCount[i]=context->width * context->height; @@ -336,15 +349,12 @@ void nsc_context_initialize(NSC_CONTEXT* context, STREAM* s) } } -void nsc_context_destroy(NSC_CONTEXT* context) +void nsc_context_free(NSC_CONTEXT* context) { - int i; - - for (i = 0;i < 4; i++) - stream_free(context->org_buf[i]); - stream_detach(context->nsc_stream->pdata); - xfree(context->bmpdata); + if (context->bmpdata) + xfree(context->bmpdata); + xfree(context); } NSC_CONTEXT* nsc_context_new(void) @@ -355,11 +365,17 @@ NSC_CONTEXT* nsc_context_new(void) return nsc_context; } -void nsc_process_message(NSC_CONTEXT* context, uint8* data, uint32 length) +void nsc_process_message(NSC_CONTEXT* context, uint16 bpp, + uint16 width, uint16 height, uint8* data, uint32 length) { + int i; STREAM* s; + s = stream_new(0); stream_attach(s, data, length); + context->bpp = bpp; + context->width = width; + context->height = height; nsc_context_initialize(context, s); /* RLE decode */ @@ -377,4 +393,12 @@ void nsc_process_message(NSC_CONTEXT* context, uint8* data, uint32 length) /* Combine ARGB planes */ nsc_combine_argb(context); + + for (i = 0;i < 4; i++) + { + if (context->org_buf[i]) + stream_free(context->org_buf[i]); + } + stream_detach(s); + stream_free(s); } diff --git a/libfreerdp-gdi/gdi.c b/libfreerdp-gdi/gdi.c index c8f1ebf9c..9029ad6e8 100644 --- a/libfreerdp-gdi/gdi.c +++ b/libfreerdp-gdi/gdi.c @@ -737,9 +737,8 @@ void gdi_surface_bits(rdpContext* context, SURFACE_BITS_COMMAND* surface_bits_co } else if (surface_bits_command->codecID == CODEC_ID_NSCODEC) { - nsc_context->width = surface_bits_command->width; - nsc_context->height = surface_bits_command->height; - nsc_process_message(nsc_context, surface_bits_command->bitmapData, surface_bits_command->bitmapDataLength); + nsc_process_message(nsc_context, surface_bits_command->bpp, surface_bits_command->width, surface_bits_command->height, + surface_bits_command->bitmapData, surface_bits_command->bitmapDataLength); gdi->image->bitmap->width = surface_bits_command->width; gdi->image->bitmap->height = surface_bits_command->height; gdi->image->bitmap->bitsPerPixel = surface_bits_command->bpp; @@ -747,7 +746,6 @@ void gdi_surface_bits(rdpContext* context, SURFACE_BITS_COMMAND* surface_bits_co gdi->image->bitmap->data = (uint8*) xrealloc(gdi->image->bitmap->data, gdi->image->bitmap->width * gdi->image->bitmap->height * 4); freerdp_image_flip(nsc_context->bmpdata, gdi->image->bitmap->data, gdi->image->bitmap->width, gdi->image->bitmap->height, 32); gdi_BitBlt(gdi->primary->hdc, surface_bits_command->destLeft, surface_bits_command->destTop, surface_bits_command->width, surface_bits_command->height, gdi->image->hdc, 0, 0, GDI_SRCCOPY); - nsc_context_destroy(nsc_context); } else if (surface_bits_command->codecID == CODEC_ID_NONE) {