Merge branch 'master' of github.com:awakecoding/FreeRDP

This commit is contained in:
Marc-André Moreau 2013-12-03 00:52:36 -05:00
commit ea9511fb0d
20 changed files with 2597 additions and 357 deletions

View File

@ -466,7 +466,6 @@ void wf_gdi_multi_opaque_rect(wfContext* wfc, MULTI_OPAQUE_RECT_ORDER* multi_opa
rect.bottom = rectangle->top + rectangle->height; rect.bottom = rectangle->top + rectangle->height;
brush = CreateSolidBrush(brush_color); brush = CreateSolidBrush(brush_color);
brush = CreateSolidBrush(brush_color);
FillRect(wfc->drawing->hdc, &rect, brush); FillRect(wfc->drawing->hdc, &rect, brush);
if (wfc->drawing == wfc->primary) if (wfc->drawing == wfc->primary)

View File

@ -182,7 +182,7 @@ void xf_Bitmap_Decompress(rdpContext* context, rdpBitmap* bitmap,
{ {
status = bitmap_decompress(data, bitmap->data, width, height, length, bpp, bpp); status = bitmap_decompress(data, bitmap->data, width, height, length, bpp, bpp);
if (status == FALSE) if (!status)
{ {
fprintf(stderr, "xf_Bitmap_Decompress: Bitmap Decompression Failed\n"); fprintf(stderr, "xf_Bitmap_Decompress: Bitmap Decompression Failed\n");
} }

View File

@ -23,6 +23,8 @@
#include <freerdp/api.h> #include <freerdp/api.h>
#include <freerdp/types.h> #include <freerdp/types.h>
#include <freerdp/codec/color.h>
#include <winpr/crt.h> #include <winpr/crt.h>
#include <winpr/stream.h> #include <winpr/stream.h>
@ -31,4 +33,7 @@ FREERDP_API BOOL bitmap_decompress(BYTE* srcData, BYTE* dstData, int width, int
FREERDP_API int freerdp_bitmap_compress(char* in_data, int width, int height, FREERDP_API int freerdp_bitmap_compress(char* in_data, int width, int height,
wStream* s, int bpp, int byte_limit, int start_line, wStream* temp_s, int e); wStream* s, int bpp, int byte_limit, int start_line, wStream* temp_s, int e);
FREERDP_API BYTE* freerdp_bitmap_compress_planar(BYTE* data, UINT32 format, int width, int height,
int scanline, BYTE* dstData, int* dstSize);
#endif /* FREERDP_CODEC_BITMAP_H */ #endif /* FREERDP_CODEC_BITMAP_H */

View File

@ -23,6 +23,20 @@
#include <freerdp/api.h> #include <freerdp/api.h>
#include <freerdp/freerdp.h> #include <freerdp/freerdp.h>
#define FREERDP_PIXEL_FORMAT_TYPE_ARGB 1
#define FREERDP_PIXEL_FORMAT_TYPE_ABGR 2
#define FREERDP_PIXEL_FLIP_NONE 0
#define FREERDP_PIXEL_FLIP_VERTICAL 1
#define FREERDP_PIXEL_FLIP_HORIZONTAL 2
#define FREERDP_PIXEL_FORMAT(_bpp, _type, _flip) \
((_bpp << 24) | (_type << 16) | (_flip << 8))
#define FREERDP_PIXEL_FORMAT_BPP(_format) (((_format) >> 24) & 0xFF)
#define FREERDP_PIXEL_FORMAT_TYPE(_format) (((_format) >> 16) & 0xFF)
#define FREERDP_PIXEL_FORMAT_FLIP(_format) (((_format) >> 8) & 0xFF)
#ifdef __cplusplus #ifdef __cplusplus
extern "C" { extern "C" {
#endif #endif

View File

@ -64,7 +64,7 @@ FREERDP_API int tls_wait_read(rdpTls* tls);
FREERDP_API int tls_wait_write(rdpTls* tls); FREERDP_API int tls_wait_write(rdpTls* tls);
FREERDP_API BOOL tls_match_hostname(char *pattern, int pattern_length, char *hostname); FREERDP_API BOOL tls_match_hostname(char *pattern, int pattern_length, char *hostname);
FREERDP_API BOOL tls_verify_certificate(rdpTls* tls, CryptoCert cert, char* hostname); FREERDP_API BOOL tls_verify_certificate(rdpTls* tls, CryptoCert cert, char* hostname, int port);
FREERDP_API void tls_print_certificate_error(char* hostname, char* fingerprint, char* hosts_file); FREERDP_API void tls_print_certificate_error(char* hostname, char* fingerprint, char* hosts_file);
FREERDP_API void tls_print_certificate_name_mismatch_error(char* hostname, char* common_name, char** alt_names, int alt_names_count); FREERDP_API void tls_print_certificate_name_mismatch_error(char* hostname, char* common_name, char** alt_names, int alt_names_count);

View File

@ -61,7 +61,7 @@ typedef void (*pPostDisconnect)(freerdp* instance);
typedef BOOL (*pAuthenticate)(freerdp* instance, char** username, char** password, char** domain); typedef BOOL (*pAuthenticate)(freerdp* instance, char** username, char** password, char** domain);
typedef BOOL (*pVerifyCertificate)(freerdp* instance, char* subject, char* issuer, char* fingerprint); typedef BOOL (*pVerifyCertificate)(freerdp* instance, char* subject, char* issuer, char* fingerprint);
typedef BOOL (*pVerifyChangedCertificate)(freerdp* instance, char* subject, char* issuer, char* new_fingerprint, char* old_fingerprint); typedef BOOL (*pVerifyChangedCertificate)(freerdp* instance, char* subject, char* issuer, char* new_fingerprint, char* old_fingerprint);
typedef int (*pVerifyX509Certificate)(freerdp* instance, BYTE* data, int length, DWORD flags); typedef int (*pVerifyX509Certificate)(freerdp* instance, BYTE* data, int length, const char* hostname, int port, DWORD flags);
typedef int (*pLogonErrorInfo)(freerdp* instance, UINT32 data, UINT32 type); typedef int (*pLogonErrorInfo)(freerdp* instance, UINT32 data, UINT32 type);

View File

@ -22,6 +22,8 @@ set(${MODULE_PREFIX}_SRCS
dsp.c dsp.c
color.c color.c
audio.c audio.c
planar.c
planar.h
bitmap_decode.c bitmap_decode.c
bitmap_encode.c bitmap_encode.c
rfx_bitstream.h rfx_bitstream.h
@ -106,3 +108,8 @@ else()
endif() endif()
set_property(TARGET ${MODULE_NAME} PROPERTY FOLDER "FreeRDP/libfreerdp") set_property(TARGET ${MODULE_NAME} PROPERTY FOLDER "FreeRDP/libfreerdp")
if(BUILD_TESTING)
add_subdirectory(test)
endif()

View File

@ -21,7 +21,11 @@
#include "config.h" #include "config.h"
#endif #endif
#include <winpr/crt.h>
#include <winpr/stream.h> #include <winpr/stream.h>
#include "planar.h"
#include <freerdp/codec/color.h> #include <freerdp/codec/color.h>
#include <freerdp/codec/bitmap.h> #include <freerdp/codec/bitmap.h>
@ -251,196 +255,12 @@ static UINT32 ExtractRunLength(UINT32 code, BYTE* pbOrderHdr, UINT32* advance)
#define RLEEXTRA #define RLEEXTRA
#include "include/bitmap.c" #include "include/bitmap.c"
#define IN_UINT8_MV(_p) (*((_p)++))
/**
* decompress an RLE color plane
* RDP6_BITMAP_STREAM
*/
static int process_rle_plane(BYTE* in, int width, int height, BYTE* out, int size)
{
int indexw;
int indexh;
int code;
int collen;
int replen;
int color;
int x;
int revcode;
BYTE* last_line;
BYTE* this_line;
BYTE* org_in;
BYTE* org_out;
org_in = in;
org_out = out;
last_line = 0;
indexh = 0;
while (indexh < height)
{
out = (org_out + width * height * 4) - ((indexh + 1) * width * 4);
color = 0;
this_line = out;
indexw = 0;
if (last_line == 0)
{
while (indexw < width)
{
code = IN_UINT8_MV(in);
replen = code & 0xf;
collen = (code >> 4) & 0xf;
revcode = (replen << 4) | collen;
if ((revcode <= 47) && (revcode >= 16))
{
replen = revcode;
collen = 0;
}
while (collen > 0)
{
color = IN_UINT8_MV(in);
*out = color;
out += 4;
indexw++;
collen--;
}
while (replen > 0)
{
*out = color;
out += 4;
indexw++;
replen--;
}
}
}
else
{
while (indexw < width)
{
code = IN_UINT8_MV(in);
replen = code & 0xf;
collen = (code >> 4) & 0xf;
revcode = (replen << 4) | collen;
if ((revcode <= 47) && (revcode >= 16))
{
replen = revcode;
collen = 0;
}
while (collen > 0)
{
x = IN_UINT8_MV(in);
if (x & 1)
{
x = x >> 1;
x = x + 1;
color = -x;
}
else
{
x = x >> 1;
color = x;
}
x = last_line[indexw * 4] + color;
*out = x;
out += 4;
indexw++;
collen--;
}
while (replen > 0)
{
x = last_line[indexw * 4] + color;
*out = x;
out += 4;
indexw++;
replen--;
}
}
}
indexh++;
last_line = this_line;
}
return (int) (in - org_in);
}
/**
* process a raw color plane
*/
static int process_raw_plane(BYTE* srcData, int width, int height, BYTE* dstData, int size)
{
int x, y;
for (y = 0; y < height; y++)
{
for (x = 0; x < width; x++)
{
dstData[(((height - y - 1) * width) + x) * 4] = srcData[((y * width) + x)];
}
}
return (width * height);
}
/**
* 4 byte bitmap decompress
* RDP6_BITMAP_STREAM
*/
static BOOL bitmap_decompress4(BYTE* srcData, BYTE* dstData, int width, int height, int size)
{
int RLE;
int code;
int NoAlpha;
int bytes_processed;
int total_processed;
code = IN_UINT8_MV(srcData);
RLE = code & 0x10;
total_processed = 1;
NoAlpha = code & 0x20;
if (NoAlpha == 0)
{
bytes_processed = process_rle_plane(srcData, width, height, dstData + 3, size - total_processed);
total_processed += bytes_processed;
srcData += bytes_processed;
}
if (RLE != 0)
{
bytes_processed = process_rle_plane(srcData, width, height, dstData + 2, size - total_processed);
total_processed += bytes_processed;
srcData += bytes_processed;
bytes_processed = process_rle_plane(srcData, width, height, dstData + 1, size - total_processed);
total_processed += bytes_processed;
srcData += bytes_processed;
bytes_processed = process_rle_plane(srcData, width, height, dstData + 0, size - total_processed);
total_processed += bytes_processed;
}
else
{
bytes_processed = process_raw_plane(srcData, width, height, dstData + 2, size - total_processed);
total_processed += bytes_processed;
srcData += bytes_processed;
bytes_processed = process_raw_plane(srcData, width, height, dstData + 1, size - total_processed);
total_processed += bytes_processed;
srcData += bytes_processed;
bytes_processed = process_raw_plane(srcData, width, height, dstData + 0, size - total_processed);
total_processed += bytes_processed + 1;
}
return (size == total_processed) ? TRUE : FALSE;
}
/** /**
* bitmap decompression routine * bitmap decompression routine
*/ */
BOOL bitmap_decompress(BYTE* srcData, BYTE* dstData, int width, int height, int size, int srcBpp, int dstBpp) BOOL bitmap_decompress(BYTE* srcData, BYTE* dstData, int width, int height, int size, int srcBpp, int dstBpp)
{ {
BYTE * TmpBfr; BYTE* TmpBfr;
if (srcBpp == 16 && dstBpp == 16) if (srcBpp == 16 && dstBpp == 16)
{ {
@ -451,7 +271,7 @@ BOOL bitmap_decompress(BYTE* srcData, BYTE* dstData, int width, int height, int
} }
else if (srcBpp == 32 && dstBpp == 32) else if (srcBpp == 32 && dstBpp == 32)
{ {
if (!bitmap_decompress4(srcData, dstData, width, height, size)) if (freerdp_bitmap_planar_decompress(srcData, dstData, width, height, size) < 0)
return FALSE; return FALSE;
} }
else if (srcBpp == 15 && dstBpp == 15) else if (srcBpp == 15 && dstBpp == 15)

View File

@ -1572,153 +1572,3 @@ int freerdp_bitmap_compress(char* in_data, int width, int height,
return lines_sent; return lines_sent;
} }
/**
* RDP6 Bitmap Test Case ([MS-RDPEGDI])
*/
const BYTE TEST_RDP6_COMPRESSED_BITMAP[220] =
"\x85\xFF\xFF\x99\xD6\x99\xD6\x99\xD6\x99\xD6\x06\x8B\x99\xD6\x99"
"\xD6\x99\xD6\x10\x84\x08\x42\x08\x42\x10\x84\x99\xD6\x99\xD6\x99"
"\xD6\x99\xD6\x06\x84\x99\xD6\x99\xD6\x99\xD6\xFF\xFF\x16\x69\x99"
"\xD6\x06\x69\x99\xD6\x04\xCC\x89\x52\x03\x6E\xFF\xFF\x02\x6E\x08"
"\x42\x01\x70\x08\x42\x71\xFF\xFF\xCE\x18\xC6\x01\x81\x08\x42\xCE"
"\x66\x29\x02\xCD\x89\x52\x03\x88\x10\x84\x99\xD6\x99\xD6\x99\xD6"
"\x00\x00\x00\x00\x00\x00\x00\x00\xD8\x99\xD6\x03\xF8\x01\x00\x00"
"\x00\x00\xF0\x66\x99\xD6\x05\x6A\x99\xD6\x00\xC4\xCC\x89\x52\x03"
"\x6E\xFF\xFF\x02\x6E\x08\x42\x01\x70\x08\x42\x71\xFF\xFF\xCE\x18"
"\xC6\x01\x81\x08\x42\xCE\x66\x29\x02\xCD\x89\x52\x03\x00\x04\xD6"
"\x99\xD6\xC3\x80\x61\x00\xA5\x80\x40\xEC\x52\x00\x5A\x00\x2D\x00"
"\x24\x00\x12\x00\x24\x00\x12\x00\x5A\x00\x2D\x00\xA5\x80\x52\x00"
"\xC3\x80\x61\x00\x00\x00\x00\x00\xCC\x89\x52\x03\x6E\xFF\xFF\x02"
"\xCB\x18\xC6\x84\x08\x42\x08\x42\x08\x42\xFF\xFF";
const BYTE TEST_RDP6_UNCOMPRESSED_BITMAP[2048] =
"\xFF\xFF\x99\xD6\x99\xD6\x99\xD6\x99\xD6\x00\x00\x00\x00\x00\x00"
"\x00\x00\x00\x00\x00\x00\x99\xD6\x99\xD6\x99\xD6\x10\x84\x08\x42"
"\x08\x42\x10\x84\x99\xD6\x99\xD6\x99\xD6\x99\xD6\x00\x00\x00\x00"
"\x00\x00\x00\x00\x00\x00\x00\x00\x99\xD6\x99\xD6\x99\xD6\xFF\xFF"
"\xFF\xFF\x99\xD6\x99\xD6\x99\xD6\x99\xD6\x00\x00\x00\x00\x00\x00"
"\x00\x00\x00\x00\x00\x00\x99\xD6\x99\xD6\x99\xD6\x10\x84\x08\x42"
"\x08\x42\x10\x84\x99\xD6\x99\xD6\x99\xD6\x99\xD6\x99\xD6\x99\xD6"
"\x99\xD6\x99\xD6\x99\xD6\x99\xD6\x99\xD6\x99\xD6\x99\xD6\xFF\xFF"
"\xFF\xFF\x99\xD6\x99\xD6\x99\xD6\x99\xD6\x99\xD6\x99\xD6\x99\xD6"
"\x99\xD6\x99\xD6\x99\xD6\x99\xD6\x99\xD6\x99\xD6\x10\x84\x08\x42"
"\x08\x42\x10\x84\x10\x84\x10\x84\x10\x84\x10\x84\x10\x84\x10\x84"
"\x10\x84\x10\x84\x10\x84\x10\x84\x10\x84\x10\x84\x99\xD6\xFF\xFF"
"\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF"
"\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x08\x42"
"\x08\x42\x08\x42\x08\x42\x08\x42\x08\x42\x08\x42\x08\x42\x08\x42"
"\x08\x42\x08\x42\x08\x42\x08\x42\x08\x42\x08\x42\x08\x42\xFF\xFF"
"\x08\x42\x08\x42\x08\x42\x08\x42\x08\x42\x08\x42\x08\x42\x08\x42"
"\x08\x42\x08\x42\x08\x42\x08\x42\x08\x42\x08\x42\x08\x42\x08\x42"
"\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF"
"\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF"
"\xFF\xFF\x10\x84\x10\x84\x10\x84\x10\x84\x10\x84\x10\x84\x10\x84"
"\x10\x84\x10\x84\x10\x84\x10\x84\x10\x84\x10\x84\x10\x84\x08\x42"
"\x08\x42\x99\xD6\x99\xD6\x99\xD6\x99\xD6\x99\xD6\x99\xD6\x99\xD6"
"\x99\xD6\x99\xD6\x99\xD6\x99\xD6\x99\xD6\x99\xD6\x99\xD6\xFF\xFF"
"\xFF\xFF\x99\xD6\x99\xD6\x99\xD6\x99\xD6\x99\xD6\x99\xD6\x99\xD6"
"\x99\xD6\x99\xD6\x99\xD6\x99\xD6\x99\xD6\x99\xD6\x10\x84\x08\x42"
"\x08\x42\x10\x84\x99\xD6\x99\xD6\x99\xD6\x00\x00\x00\x00\x00\x00"
"\x00\x00\x00\x00\x00\x00\x99\xD6\x99\xD6\x99\xD6\x99\xD6\xFF\xFF"
"\xFF\xFF\x99\xD6\x99\xD6\x99\xD6\x00\x00\x00\x00\x00\x00\x00\x00"
"\x00\x00\x00\x00\x99\xD6\x99\xD6\x99\xD6\x99\xD6\x10\x84\x08\x42"
"\x08\x42\x10\x84\x99\xD6\x99\xD6\x99\xD6\x00\x00\x00\x00\x00\x00"
"\x00\x00\x00\x00\x00\x00\x99\xD6\x99\xD6\x99\xD6\x99\xD6\xFF\xFF"
"\xFF\xFF\x99\xD6\x99\xD6\x99\xD6\x00\x00\x00\x00\x00\x00\x00\x00"
"\x00\x00\x00\x00\x99\xD6\x99\xD6\x99\xD6\x99\xD6\x10\x84\x08\x42"
"\x08\x42\x10\x84\x99\xD6\x99\xD6\x99\xD6\x99\xD6\x99\xD6\x99\xD6"
"\x99\xD6\x99\xD6\x99\xD6\x99\xD6\x99\xD6\x99\xD6\x99\xD6\xFF\xFF"
"\xFF\xFF\x99\xD6\x99\xD6\x99\xD6\x99\xD6\x99\xD6\x99\xD6\x99\xD6"
"\x99\xD6\x99\xD6\x99\xD6\x99\xD6\x99\xD6\x99\xD6\x10\x84\x08\x42"
"\x08\x42\x10\x84\x99\xD6\x99\xD6\x99\xD6\x99\xD6\x99\xD6\x99\xD6"
"\x99\xD6\x99\xD6\x99\xD6\x99\xD6\x99\xD6\x99\xD6\x99\xD6\xFF\xFF"
"\xFF\xFF\x99\xD6\x99\xD6\x99\xD6\x99\xD6\x99\xD6\x99\xD6\x99\xD6"
"\x99\xD6\x99\xD6\x99\xD6\x99\xD6\x99\xD6\x99\xD6\x10\x84\x08\x42"
"\x08\x42\x10\x84\x99\xD6\x99\xD6\x99\xD6\x99\xD6\x99\xD6\x99\xD6"
"\x99\xD6\x99\xD6\x99\xD6\x99\xD6\x99\xD6\x99\xD6\x99\xD6\xFF\xFF"
"\xFF\xFF\x99\xD6\x99\xD6\x99\xD6\x99\xD6\x99\xD6\x99\xD6\x99\xD6"
"\x99\xD6\x99\xD6\x99\xD6\x99\xD6\x99\xD6\x99\xD6\x10\x84\x08\x42"
"\x08\x42\x10\x84\x99\xD6\x99\xD6\x99\xD6\x99\xD6\x99\xD6\x99\xD6"
"\x99\xD6\x99\xD6\x99\xD6\x99\xD6\x99\xD6\x99\xD6\x99\xD6\xFF\xFF"
"\xFF\xFF\x99\xD6\x99\xD6\x99\xD6\x99\xD6\x99\xD6\x99\xD6\x99\xD6"
"\x99\xD6\x99\xD6\x99\xD6\x99\xD6\x99\xD6\x99\xD6\x10\x84\x08\x42"
"\x08\x42\x10\x84\x99\xD6\x99\xD6\x99\xD6\x99\xD6\x99\xD6\x99\xD6"
"\x99\xD6\x99\xD6\x99\xD6\x99\xD6\x99\xD6\x99\xD6\x99\xD6\xFF\xFF"
"\xFF\xFF\x99\xD6\x99\xD6\x99\xD6\x99\xD6\x99\xD6\x99\xD6\x99\xD6"
"\x99\xD6\x99\xD6\x99\xD6\x99\xD6\x99\xD6\x99\xD6\x10\x84\x08\x42"
"\x08\x42\x10\x84\x99\xD6\x99\xD6\x99\xD6\x99\xD6\x99\xD6\x99\xD6"
"\x99\xD6\x99\xD6\x99\xD6\x99\xD6\x99\xD6\x99\xD6\x99\xD6\xFF\xFF"
"\xFF\xFF\x99\xD6\x99\xD6\x99\xD6\x99\xD6\x99\xD6\x99\xD6\x99\xD6"
"\x99\xD6\x99\xD6\x99\xD6\x99\xD6\x99\xD6\x99\xD6\x10\x84\x08\x42"
"\x08\x42\x10\x84\x99\xD6\x99\xD6\x99\xD6\x99\xD6\x99\xD6\x99\xD6"
"\x99\xD6\x99\xD6\x99\xD6\x99\xD6\x99\xD6\x99\xD6\x99\xD6\xFF\xFF"
"\xFF\xFF\x99\xD6\x99\xD6\x99\xD6\x99\xD6\x99\xD6\x99\xD6\x99\xD6"
"\x99\xD6\x99\xD6\x99\xD6\x99\xD6\x99\xD6\x99\xD6\x10\x84\x08\x42"
"\x08\x42\x10\x84\x99\xD6\x99\xD6\x99\xD6\x99\xD6\x99\xD6\x99\xD6"
"\x99\xD6\x99\xD6\x99\xD6\x99\xD6\x99\xD6\x99\xD6\x99\xD6\xFF\xFF"
"\xFF\xFF\x99\xD6\x99\xD6\x99\xD6\x99\xD6\x99\xD6\x99\xD6\x99\xD6"
"\x99\xD6\x99\xD6\x99\xD6\x99\xD6\x99\xD6\x99\xD6\x10\x84\x08\x42"
"\x08\x42\x10\x84\x10\x84\x10\x84\x10\x84\x10\x84\x10\x84\x10\x84"
"\x10\x84\x10\x84\x10\x84\x10\x84\x10\x84\x10\x84\x99\xD6\xFF\xFF"
"\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF"
"\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x08\x42"
"\x08\x42\x08\x42\x08\x42\x08\x42\x08\x42\x08\x42\x08\x42\x08\x42"
"\x08\x42\x08\x42\x08\x42\x08\x42\x08\x42\x08\x42\x08\x42\xFF\xFF"
"\x08\x42\x08\x42\x08\x42\x08\x42\x08\x42\x08\x42\x08\x42\x08\x42"
"\x08\x42\x08\x42\x08\x42\x08\x42\x08\x42\x08\x42\x08\x42\x08\x42"
"\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF"
"\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF"
"\xFF\xFF\x10\x84\x10\x84\x10\x84\x10\x84\x10\x84\x10\x84\x10\x84"
"\x10\x84\x10\x84\x10\x84\x10\x84\x10\x84\x10\x84\x10\x84\x08\x42"
"\x08\x42\x99\xD6\x99\xD6\x99\xD6\x99\xD6\x99\xD6\x99\xD6\x99\xD6"
"\x99\xD6\x99\xD6\x99\xD6\x99\xD6\x99\xD6\x99\xD6\x99\xD6\xFF\xFF"
"\xFF\xFF\x99\xD6\x99\xD6\x99\xD6\x99\xD6\x99\xD6\x99\xD6\x99\xD6"
"\x99\xD6\x99\xD6\x99\xD6\x99\xD6\x99\xD6\x99\xD6\x10\x84\x08\x42"
"\x08\x42\x10\x84\x99\xD6\x99\xD6\x99\xD6\x99\xD6\x99\xD6\x99\xD6"
"\x99\xD6\x99\xD6\x99\xD6\x99\xD6\x99\xD6\x99\xD6\x99\xD6\xFF\xFF"
"\xFF\xFF\x99\xD6\x99\xD6\x99\xD6\x99\xD6\x99\xD6\x99\xD6\x99\xD6"
"\x99\xD6\x99\xD6\x99\xD6\x99\xD6\x99\xD6\x99\xD6\x10\x84\x08\x42"
"\x08\x42\x10\x84\x99\xD6\x99\xD6\x99\xD6\x00\x00\x00\x00\x99\xD6"
"\x99\xD6\x99\xD6\x99\xD6\x00\x00\x00\x00\x99\xD6\x99\xD6\xFF\xFF"
"\xFF\xFF\x99\xD6\x99\xD6\x99\xD6\x00\x00\x00\x00\x99\xD6\x99\xD6"
"\x99\xD6\x99\xD6\x00\x00\x00\x00\x99\xD6\x99\xD6\x10\x84\x08\x42"
"\x08\x42\x10\x84\x99\xD6\x99\xD6\x99\xD6\x99\xD6\x00\x00\x00\x00"
"\x99\xD6\x99\xD6\x00\x00\x00\x00\x99\xD6\x99\xD6\x99\xD6\xFF\xFF"
"\xFF\xFF\x99\xD6\x99\xD6\x99\xD6\x99\xD6\x00\x00\x00\x00\x99\xD6"
"\x99\xD6\x00\x00\x00\x00\x99\xD6\x99\xD6\x99\xD6\x10\x84\x08\x42"
"\x08\x42\x10\x84\x99\xD6\x99\xD6\x99\xD6\x99\xD6\x99\xD6\x00\x00"
"\x00\x00\x00\x00\x00\x00\x99\xD6\x99\xD6\x99\xD6\x99\xD6\xFF\xFF"
"\xFF\xFF\x99\xD6\x99\xD6\x99\xD6\x99\xD6\x99\xD6\x00\x00\x00\x00"
"\x00\x00\x00\x00\x99\xD6\x99\xD6\x99\xD6\x99\xD6\x10\x84\x08\x42"
"\x08\x42\x10\x84\x99\xD6\x99\xD6\x99\xD6\x99\xD6\x99\xD6\x99\xD6"
"\x00\x00\x00\x00\x99\xD6\x99\xD6\x99\xD6\x99\xD6\x99\xD6\xFF\xFF"
"\xFF\xFF\x99\xD6\x99\xD6\x99\xD6\x99\xD6\x99\xD6\x99\xD6\x00\x00"
"\x00\x00\x99\xD6\x99\xD6\x99\xD6\x99\xD6\x99\xD6\x10\x84\x08\x42"
"\x08\x42\x10\x84\x99\xD6\x99\xD6\x99\xD6\x99\xD6\x99\xD6\x00\x00"
"\x00\x00\x00\x00\x00\x00\x99\xD6\x99\xD6\x99\xD6\x99\xD6\xFF\xFF"
"\xFF\xFF\x99\xD6\x99\xD6\x99\xD6\x99\xD6\x99\xD6\x00\x00\x00\x00"
"\x00\x00\x00\x00\x99\xD6\x99\xD6\x99\xD6\x99\xD6\x10\x84\x08\x42"
"\x08\x42\x10\x84\x99\xD6\x99\xD6\x99\xD6\x99\xD6\x00\x00\x00\x00"
"\x99\xD6\x99\xD6\x00\x00\x00\x00\x99\xD6\x99\xD6\x99\xD6\xFF\xFF"
"\xFF\xFF\x99\xD6\x99\xD6\x99\xD6\x99\xD6\x00\x00\x00\x00\x99\xD6"
"\x99\xD6\x00\x00\x00\x00\x99\xD6\x99\xD6\x99\xD6\x10\x84\x08\x42"
"\x08\x42\x10\x84\x99\xD6\x99\xD6\x99\xD6\x00\x00\x00\x00\x99\xD6"
"\x99\xD6\x99\xD6\x99\xD6\x00\x00\x00\x00\x99\xD6\x99\xD6\xFF\xFF"
"\xFF\xFF\x99\xD6\x99\xD6\x99\xD6\x00\x00\x00\x00\x99\xD6\x99\xD6"
"\x99\xD6\x99\xD6\x00\x00\x00\x00\x99\xD6\x99\xD6\x10\x84\x08\x42"
"\x08\x42\x10\x84\x99\xD6\x99\xD6\x99\xD6\x99\xD6\x99\xD6\x99\xD6"
"\x99\xD6\x99\xD6\x99\xD6\x99\xD6\x99\xD6\x99\xD6\x99\xD6\xFF\xFF"
"\xFF\xFF\x99\xD6\x99\xD6\x99\xD6\x99\xD6\x99\xD6\x99\xD6\x99\xD6"
"\x99\xD6\x99\xD6\x99\xD6\x99\xD6\x99\xD6\x99\xD6\x10\x84\x08\x42"
"\x08\x42\x10\x84\x99\xD6\x99\xD6\x99\xD6\x99\xD6\x99\xD6\x99\xD6"
"\x99\xD6\x99\xD6\x99\xD6\x99\xD6\x99\xD6\x99\xD6\x99\xD6\xFF\xFF"
"\xFF\xFF\x99\xD6\x99\xD6\x99\xD6\x99\xD6\x99\xD6\x99\xD6\x99\xD6"
"\x99\xD6\x99\xD6\x99\xD6\x99\xD6\x99\xD6\x99\xD6\x10\x84\x08\x42"
"\x08\x42\x10\x84\x10\x84\x10\x84\x10\x84\x10\x84\x10\x84\x10\x84"
"\x10\x84\x10\x84\x10\x84\x10\x84\x10\x84\x10\x84\x99\xD6\xFF\xFF"
"\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF"
"\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x08\x42"
"\x08\x42\x08\x42\x08\x42\x08\x42\x08\x42\x08\x42\x08\x42\x08\x42"
"\x08\x42\x08\x42\x08\x42\x08\x42\x08\x42\x08\x42\x08\x42\xFF\xFF";

859
libfreerdp/codec/planar.c Normal file
View File

@ -0,0 +1,859 @@
/**
* FreeRDP: A Remote Desktop Protocol Implementation
* RDP6 Planar Codec
*
* Copyright 2013 Marc-Andre Moreau <marcandre.moreau@gmail.com>
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
#ifdef HAVE_CONFIG_H
#include "config.h"
#endif
#include <winpr/crt.h>
#include <winpr/print.h>
#include <freerdp/codec/bitmap.h>
#include "planar.h"
static int freerdp_bitmap_planar_decompress_plane_rle(BYTE* inPlane, int width, int height, BYTE* outPlane, int srcSize)
{
int k;
int x, y;
BYTE* srcp;
BYTE* dstp;
UINT32 pixel;
int scanline;
int cRawBytes;
int nRunLength;
int deltaValue;
BYTE controlByte;
BYTE* currentScanline;
BYTE* previousScanline;
k = 0;
srcp = inPlane;
dstp = outPlane;
scanline = width * 4;
previousScanline = NULL;
y = 0;
while (y < height)
{
pixel = 0;
dstp = (outPlane + height * scanline) - ((y + 1) * scanline);
currentScanline = dstp;
x = 0;
while (x < width)
{
controlByte = *srcp;
srcp++;
if ((srcp - inPlane) > srcSize)
{
printf("freerdp_bitmap_planar_decompress_plane_rle: error reading input buffer\n");
return -1;
}
nRunLength = PLANAR_CONTROL_BYTE_RUN_LENGTH(controlByte);
cRawBytes = PLANAR_CONTROL_BYTE_RAW_BYTES(controlByte);
//printf("CONTROL(%d, %d)\n", cRawBytes, nRunLength);
if (nRunLength == 1)
{
nRunLength = cRawBytes + 16;
cRawBytes = 0;
}
else if (nRunLength == 2)
{
nRunLength = cRawBytes + 32;
cRawBytes = 0;
}
#if 0
printf("y: %d cRawBytes: %d nRunLength: %d\n", y, cRawBytes, nRunLength);
printf("RAW[");
for (k = 0; k < cRawBytes; k++)
{
printf("0x%02X%s", srcp[k],
((k + 1) == cRawBytes) ? "" : ", ");
}
printf("] RUN[%d]\n", nRunLength);
#endif
if (((dstp + (cRawBytes + nRunLength)) - currentScanline) > width * 4)
{
printf("freerdp_bitmap_planar_decompress_plane_rle: too many pixels in scanline\n");
return -1;
}
if (!previousScanline)
{
/* first scanline, absolute values */
while (cRawBytes > 0)
{
pixel = *srcp;
srcp++;
*dstp = pixel;
dstp += 4;
x++;
cRawBytes--;
}
while (nRunLength > 0)
{
*dstp = pixel;
dstp += 4;
x++;
nRunLength--;
}
}
else
{
/* delta values relative to previous scanline */
while (cRawBytes > 0)
{
deltaValue = *srcp;
srcp++;
if (deltaValue & 1)
{
deltaValue = deltaValue >> 1;
deltaValue = deltaValue + 1;
pixel = -deltaValue;
}
else
{
deltaValue = deltaValue >> 1;
pixel = deltaValue;
}
deltaValue = previousScanline[x * 4] + pixel;
*dstp = deltaValue;
dstp += 4;
x++;
cRawBytes--;
}
while (nRunLength > 0)
{
deltaValue = previousScanline[x * 4] + pixel;
*dstp = deltaValue;
dstp += 4;
x++;
nRunLength--;
}
}
}
previousScanline = currentScanline;
y++;
}
return (int) (srcp - inPlane);
}
static int freerdp_bitmap_planar_decompress_plane_raw(BYTE* srcData, int width, int height, BYTE* dstData, int size)
{
int x, y;
for (y = 0; y < height; y++)
{
for (x = 0; x < width; x++)
{
dstData[(((height - y - 1) * width) + x) * 4] = srcData[((y * width) + x)];
}
}
return (width * height);
}
int freerdp_bitmap_planar_decompress(BYTE* srcData, BYTE* dstData, int width, int height, int size)
{
BYTE* srcp;
int dstSize;
BYTE FormatHeader;
srcp = srcData;
FormatHeader = *srcp;
srcp++;
if (!(FormatHeader & PLANAR_FORMAT_HEADER_NA))
{
if (FormatHeader & PLANAR_FORMAT_HEADER_RLE)
{
dstSize = freerdp_bitmap_planar_decompress_plane_rle(srcp, width, height, dstData + 3, size - (srcp - srcData));
if (dstSize < 0)
return -1;
srcp += dstSize;
}
else
{
dstSize = freerdp_bitmap_planar_decompress_plane_raw(srcp, width, height, dstData + 3, size - (srcp - srcData));
srcp += dstSize;
}
}
if (FormatHeader & PLANAR_FORMAT_HEADER_RLE)
{
dstSize = freerdp_bitmap_planar_decompress_plane_rle(srcp, width, height, dstData + 2, size - (srcp - srcData));
if (dstSize < 0)
return -1;
srcp += dstSize;
dstSize = freerdp_bitmap_planar_decompress_plane_rle(srcp, width, height, dstData + 1, size - (srcp - srcData));
if (dstSize < 0)
return -1;
srcp += dstSize;
dstSize = freerdp_bitmap_planar_decompress_plane_rle(srcp, width, height, dstData + 0, size - (srcp - srcData));
if (dstSize < 0)
return -1;
srcp += dstSize;
}
else
{
dstSize = freerdp_bitmap_planar_decompress_plane_raw(srcp, width, height, dstData + 2, size - (srcp - srcData));
srcp += dstSize;
dstSize = freerdp_bitmap_planar_decompress_plane_raw(srcp, width, height, dstData + 1, size - (srcp - srcData));
srcp += dstSize;
dstSize = freerdp_bitmap_planar_decompress_plane_raw(srcp, width, height, dstData + 0, size - (srcp - srcData));
srcp += dstSize;
srcp++;
}
return (size == (srcp - srcData)) ? 0 : -1;
}
int freerdp_split_color_planes(BYTE* data, UINT32 format, int width, int height, int scanline, BYTE* planes[5])
{
int bpp;
int i, j, k;
k = 0;
bpp = FREERDP_PIXEL_FORMAT_BPP(format);
if (bpp == 32)
{
UINT32* pixel;
for (i = height - 1; i >= 0; i--)
{
pixel = (UINT32*) &data[scanline * i];
for (j = 0; j < width; j++)
{
GetARGB32(planes[0][k], planes[1][k], planes[2][k], planes[3][k], *pixel);
pixel++;
k++;
}
}
}
else if (bpp == 24)
{
UINT32* pixel;
for (i = height - 1; i >= 0; i--)
{
pixel = (UINT32*) &data[scanline * i];
for (j = 0; j < width; j++)
{
GetRGB32(planes[1][k], planes[2][k], planes[3][k], *pixel);
planes[0][k] = 0xFF; /* A */
pixel++;
k++;
}
}
}
return 0;
}
struct _PLANAR_RLE_CONTEXT
{
int width;
int height;
BYTE* output;
int nRunLength;
int cRawBytes;
BYTE* rawValues;
BYTE* rawScanline;
BYTE* outPlane;
int outPlaneSize;
int outSegmentSize;
int nControlBytes;
};
typedef struct _PLANAR_RLE_CONTEXT PLANAR_RLE_CONTEXT;
int freerdp_bitmap_planar_compress_plane_rle_segment(PLANAR_RLE_CONTEXT* rle, int position)
{
int k;
if (position < 0)
printf("B");
else if (position == 0)
printf("M");
else
printf("E");
printf(" RAW[");
for (k = 0; k < rle->cRawBytes; k++)
{
printf("0x%02X%s", rle->rawValues[k],
((k + 1) == rle->cRawBytes) ? "" : ", ");
}
printf("] RUN[%d]\n", rle->nRunLength);
while ((rle->cRawBytes != 0) || (rle->nRunLength != 0))
{
printf("cRawBytes: %d nRunLength: %d\n", rle->cRawBytes, rle->nRunLength);
if (rle->nRunLength < 3)
{
rle->cRawBytes += rle->nRunLength;
rle->nRunLength = 0;
}
if ((rle->rawValues - rle->rawScanline) > rle->width)
{
printf("rawValues overflow! %d\n", rle->rawValues - rle->rawScanline);
return 0;
}
if (rle->cRawBytes > 15)
{
rle->nControlBytes = 1;
rle->outSegmentSize = 15 + rle->nControlBytes;
if (((rle->output - rle->outPlane) + rle->outSegmentSize) > rle->outPlaneSize)
{
printf("overflow: %d > %d\n", ((rle->output - rle->outPlane) + rle->outSegmentSize), rle->outPlaneSize);
return -1;
}
*rle->output = PLANAR_CONTROL_BYTE(0, 15);
rle->output++;
CopyMemory(rle->output, rle->rawValues, 15);
rle->cRawBytes -= 15;
rle->rawValues += 15;
rle->output += 15;
/* continue */
}
else if (rle->cRawBytes == 0)
{
if (rle->nRunLength > 47)
{
rle->nControlBytes = 1;
rle->outSegmentSize = rle->nControlBytes;
if (((rle->output - rle->outPlane) + rle->outSegmentSize) > rle->outPlaneSize)
{
printf("overflow: %d > %d\n", ((rle->output - rle->outPlane) + rle->outSegmentSize), rle->outPlaneSize);
return -1;
}
*rle->output = PLANAR_CONTROL_BYTE(2, 15);
rle->nRunLength -= 47;
rle->output++;
/* continue */
}
else if (rle->nRunLength > 31)
{
rle->nControlBytes = 1;
rle->outSegmentSize = rle->nControlBytes;
if (((rle->output - rle->outPlane) + rle->outSegmentSize) > rle->outPlaneSize)
{
printf("overflow: %d > %d\n", ((rle->output - rle->outPlane) + rle->outSegmentSize), rle->outPlaneSize);
return -1;
}
*rle->output = PLANAR_CONTROL_BYTE(2, (rle->nRunLength - 32));
rle->nRunLength -= 32;
rle->output++;
return 0; /* finish */
}
else if (rle->nRunLength > 15)
{
rle->nControlBytes = 1;
rle->outSegmentSize = rle->nControlBytes;
if (((rle->output - rle->outPlane) + rle->outSegmentSize) > rle->outPlaneSize)
{
printf("overflow: %d > %d\n", ((rle->output - rle->outPlane) + rle->outSegmentSize), rle->outPlaneSize);
return -1;
}
*rle->output = PLANAR_CONTROL_BYTE(1, (rle->nRunLength - 16));
rle->nRunLength -= 16;
rle->output++;
return 0; /* finish */
}
else
{
rle->nControlBytes = 1;
rle->outSegmentSize = rle->cRawBytes + rle->nControlBytes;
if (((rle->output - rle->outPlane) + rle->outSegmentSize) > rle->outPlaneSize)
{
printf("overflow: %d > %d\n", ((rle->output - rle->outPlane) + rle->outSegmentSize), rle->outPlaneSize);
return -1;
}
*rle->output = PLANAR_CONTROL_BYTE(rle->nRunLength, rle->cRawBytes);
rle->output++;
if (rle->cRawBytes)
{
CopyMemory(rle->output, rle->rawValues, rle->cRawBytes);
rle->rawValues += (rle->cRawBytes + rle->nRunLength);
rle->output += rle->cRawBytes;
}
rle->cRawBytes = 0;
rle->nRunLength = 0;
return 0; /* finish */
}
}
else if (rle->cRawBytes < 16)
{
if (rle->nRunLength > 15)
{
rle->nControlBytes = 2;
rle->outSegmentSize = rle->cRawBytes + rle->nControlBytes;
if (((rle->output - rle->outPlane) + rle->outSegmentSize) > rle->outPlaneSize)
{
printf("overflow: %d > %d\n", ((rle->output - rle->outPlane) + rle->outSegmentSize), rle->outPlaneSize);
return -1;
}
if ((!rle->rawValues[rle->cRawBytes - 1]) && (rle->cRawBytes == 1))
{
//rle->rawValues += (rle->cRawBytes + rle->nRunLength);
//rle->cRawBytes = 0;
}
*rle->output = PLANAR_CONTROL_BYTE(15, rle->cRawBytes);
rle->output++;
if (rle->cRawBytes)
{
CopyMemory(rle->output, rle->rawValues, rle->cRawBytes);
rle->rawValues += (rle->cRawBytes + rle->nRunLength);
rle->output += rle->cRawBytes;
rle->cRawBytes = 0;
}
rle->nRunLength -= 15;
rle->cRawBytes = 0;
/* continue */
}
else
{
rle->nControlBytes = 1;
rle->outSegmentSize = rle->cRawBytes + rle->nControlBytes;
if (((rle->output - rle->outPlane) + rle->outSegmentSize) > rle->outPlaneSize)
{
printf("overflow: %d > %d\n", ((rle->output - rle->outPlane) + rle->outSegmentSize), rle->outPlaneSize);
return -1;
}
if ((!rle->rawValues[rle->cRawBytes - 1]) && (rle->cRawBytes == 1))
{
//rle->rawValues += (rle->cRawBytes + rle->nRunLength);
//rle->cRawBytes = 0;
}
*rle->output = PLANAR_CONTROL_BYTE(rle->nRunLength, rle->cRawBytes);
rle->output++;
if (rle->cRawBytes)
{
CopyMemory(rle->output, rle->rawValues, rle->cRawBytes);
rle->rawValues += (rle->cRawBytes + rle->nRunLength);
rle->output += rle->cRawBytes;
}
rle->cRawBytes = 0;
rle->nRunLength = 0;
return 0; /* finish */
}
}
}
return 0;
}
BYTE* freerdp_bitmap_planar_compress_plane_rle(BYTE* inPlane, int width, int height, BYTE* outPlane, int* dstSize)
{
int i, j;
int cSegments;
PLANAR_RLE_CONTEXT rle_s;
PLANAR_RLE_CONTEXT* rle = &rle_s;
cSegments = 0;
if (!outPlane)
{
rle->outPlaneSize = width * height * 2;
outPlane = malloc(rle->outPlaneSize);
}
else
{
rle->outPlaneSize = *dstSize;
}
rle->output = outPlane;
rle->outPlane = outPlane;
rle->width = width;
rle->height = height;
for (i = 0; i < height; i++)
{
rle->cRawBytes = 1;
rle->nRunLength = 0;
rle->rawScanline = &inPlane[i * width];
rle->rawValues = rle->rawScanline;
for (j = 1; j < width; j++)
{
printf("j: %d cRawBytes: %d nRunLength: %d\n", j, rle->cRawBytes, rle->nRunLength);
if (rle->rawScanline[j] == rle->rawValues[rle->cRawBytes - 1])
{
rle->nRunLength++;
continue;
}
rle->cRawBytes++;
if (rle->nRunLength < 3)
continue;
if (freerdp_bitmap_planar_compress_plane_rle_segment(rle, (j == 1) ? -1 : 0) < 0)
return NULL;
}
if (rle->nRunLength < 3)
{
rle->cRawBytes += rle->nRunLength;
rle->nRunLength = 0;
}
if (freerdp_bitmap_planar_compress_plane_rle_segment(rle, 1) < 0)
return NULL;
}
*dstSize = (rle->output - outPlane);
return outPlane;
}
int freerdp_bitmap_planar_compress_planes_rle(BYTE* inPlanes[5], int width, int height, BYTE* outPlanes, int* dstSizes)
{
int outPlanesSize = width * height * 4;
#if 0
dstSizes[0] = outPlanesSize;
if (!freerdp_bitmap_planar_compress_plane_rle(inPlanes[0], width, height, outPlanes, &dstSizes[0]))
return 0;
outPlanes += dstSizes[0];
outPlanesSize -= dstSizes[0];
#else
dstSizes[0] = 0;
#endif
dstSizes[1] = outPlanesSize;
printf("PlaneR\n");
if (!freerdp_bitmap_planar_compress_plane_rle(inPlanes[1], width, height, outPlanes, &dstSizes[1]))
return 0;
outPlanes += dstSizes[1];
outPlanesSize -= dstSizes[1];
dstSizes[2] = outPlanesSize;
printf("PlaneG\n");
if (!freerdp_bitmap_planar_compress_plane_rle(inPlanes[2], width, height, outPlanes, &dstSizes[2]))
return 0;
outPlanes += dstSizes[2];
outPlanesSize -= dstSizes[2];
dstSizes[3] = outPlanesSize;
printf("PlaneB\n");
if (!freerdp_bitmap_planar_compress_plane_rle(inPlanes[3], width, height, outPlanes, &dstSizes[3]))
return 0;
outPlanes += dstSizes[3];
outPlanesSize -= dstSizes[3];
return 1;
}
BYTE* freerdp_bitmap_planar_delta_encode_plane(BYTE* inPlane, int width, int height, BYTE* outPlane)
{
char s2c;
BYTE u2c;
int delta;
int i, j, k;
if (!outPlane)
{
outPlane = (BYTE*) malloc(width * height);
}
k = 0;
for (i = 0; i < height; i++)
{
for (j = 0; j < width; j++)
{
if (i < 1)
{
delta = inPlane[j];
s2c = (delta >= 0) ? (char) delta : (char) (~((BYTE) (delta * -1)) + 1);
}
else
{
delta = inPlane[(i * width) + j] - inPlane[((i - 1) * width) + j];
s2c = (delta >= 0) ? (char) delta : (char) (~((BYTE) (delta * -1)) + 1);
s2c = (s2c >= 0) ? (s2c << 1) : (char) (((~((BYTE) s2c) + 1) << 1) - 1);
}
u2c = (BYTE) s2c;
outPlane[(i * width) + j] = u2c;
k++;
}
}
return outPlane;
}
int freerdp_bitmap_planar_delta_encode_planes(BYTE* inPlanes[5], int width, int height, BYTE* outPlanes[5])
{
freerdp_bitmap_planar_delta_encode_plane(inPlanes[0], width, height, outPlanes[0]);
freerdp_bitmap_planar_delta_encode_plane(inPlanes[1], width, height, outPlanes[1]);
freerdp_bitmap_planar_delta_encode_plane(inPlanes[2], width, height, outPlanes[2]);
freerdp_bitmap_planar_delta_encode_plane(inPlanes[3], width, height, outPlanes[3]);
return 0;
}
BYTE* freerdp_bitmap_compress_planar(BYTE* data, UINT32 format, int width, int height, int scanline, BYTE* dstData, int* dstSize)
{
int size;
BYTE* dstp;
int planeSize;
int dstSizes[4];
BYTE* planes[5];
BYTE* planesBuffer;
BYTE* deltaPlanes[5];
BYTE* deltaPlanesBuffer;
BYTE* rlePlanes[4];
BYTE* rlePlanesBuffer;
BYTE FormatHeader = 0;
FormatHeader |= PLANAR_FORMAT_HEADER_NA;
planeSize = width * height;
planesBuffer = malloc(planeSize * 5);
planes[0] = &planesBuffer[planeSize * 0];
planes[1] = &planesBuffer[planeSize * 1];
planes[2] = &planesBuffer[planeSize * 2];
planes[3] = &planesBuffer[planeSize * 3];
planes[4] = &planesBuffer[planeSize * 4];
deltaPlanesBuffer = malloc(planeSize * 5);
deltaPlanes[0] = &deltaPlanesBuffer[planeSize * 0];
deltaPlanes[1] = &deltaPlanesBuffer[planeSize * 1];
deltaPlanes[2] = &deltaPlanesBuffer[planeSize * 2];
deltaPlanes[3] = &deltaPlanesBuffer[planeSize * 3];
deltaPlanes[4] = &deltaPlanesBuffer[planeSize * 4];
rlePlanesBuffer = malloc(planeSize * 4);
freerdp_split_color_planes(data, format, width, height, scanline, planes);
freerdp_bitmap_planar_delta_encode_planes(planes, width, height, deltaPlanes);
if (freerdp_bitmap_planar_compress_planes_rle(deltaPlanes, width, height, rlePlanesBuffer, (int*) &dstSizes) > 0)
{
int offset = 0;
FormatHeader |= PLANAR_FORMAT_HEADER_RLE;
rlePlanes[0] = &rlePlanesBuffer[offset];
offset += dstSizes[0];
rlePlanes[1] = &rlePlanesBuffer[offset];
offset += dstSizes[1];
rlePlanes[2] = &rlePlanesBuffer[offset];
offset += dstSizes[2];
rlePlanes[3] = &rlePlanesBuffer[offset];
offset += dstSizes[3];
printf("R: [%d/%d] G: [%d/%d] B: [%d/%d]\n",
dstSizes[1], planeSize, dstSizes[2], planeSize, dstSizes[3], planeSize);
}
if (!dstData)
{
size = 1;
if (!(FormatHeader & PLANAR_FORMAT_HEADER_NA))
{
if (FormatHeader & PLANAR_FORMAT_HEADER_RLE)
size += dstSizes[0];
else
size += planeSize;
}
if (FormatHeader & PLANAR_FORMAT_HEADER_RLE)
size += (dstSizes[1] + dstSizes[2] + dstSizes[3]);
else
size += (planeSize * 3);
if (!(FormatHeader & PLANAR_FORMAT_HEADER_RLE))
size++;
dstData = malloc(size);
*dstSize = size;
}
dstp = dstData;
*dstp = FormatHeader; /* FormatHeader */
dstp++;
/* AlphaPlane */
if (!(FormatHeader & PLANAR_FORMAT_HEADER_NA))
{
if (FormatHeader & PLANAR_FORMAT_HEADER_RLE)
{
CopyMemory(dstp, rlePlanes[0], dstSizes[0]); /* Alpha */
dstp += dstSizes[0];
}
else
{
CopyMemory(dstp, planes[0], planeSize); /* Alpha */
dstp += planeSize;
}
}
/* LumaOrRedPlane */
if (FormatHeader & PLANAR_FORMAT_HEADER_RLE)
{
CopyMemory(dstp, rlePlanes[1], dstSizes[1]); /* Red */
dstp += dstSizes[1];
}
else
{
CopyMemory(dstp, planes[1], planeSize); /* Red */
dstp += planeSize;
}
/* OrangeChromaOrGreenPlane */
if (FormatHeader & PLANAR_FORMAT_HEADER_RLE)
{
CopyMemory(dstp, rlePlanes[2], dstSizes[2]); /* Green */
dstp += dstSizes[2];
}
else
{
CopyMemory(dstp, planes[2], planeSize); /* Green */
dstp += planeSize;
}
/* GreenChromeOrBluePlane */
if (FormatHeader & PLANAR_FORMAT_HEADER_RLE)
{
CopyMemory(dstp, rlePlanes[3], dstSizes[3]); /* Blue */
dstp += dstSizes[3];
}
else
{
CopyMemory(dstp, planes[3], planeSize); /* Blue */
dstp += planeSize;
}
/* Pad1 (1 byte) */
if (!(FormatHeader & PLANAR_FORMAT_HEADER_RLE))
{
*dstp = 0;
dstp++;
}
size = (dstp - dstData);
*dstSize = size;
free(rlePlanesBuffer);
free(deltaPlanesBuffer);
free(planesBuffer);
return dstData;
}

78
libfreerdp/codec/planar.h Normal file
View File

@ -0,0 +1,78 @@
/**
* FreeRDP: A Remote Desktop Protocol Implementation
* RDP6 Planar Codec
*
* Copyright 2013 Marc-Andre Moreau <marcandre.moreau@gmail.com>
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
#ifndef FREERDP_CODEC_PLANAR_PRIVATE_H
#define FREERDP_CODEC_PLANAR_PRIVATE_H
#include <winpr/crt.h>
#include <freerdp/codec/color.h>
#define PLANAR_CONTROL_BYTE(_nRunLength, _cRawBytes) \
((_nRunLength & 0x0F) | ((_cRawBytes & 0x0F) << 4)) + \
(printf("CONTROL_BYTE(%d, %d)\n", _cRawBytes, _nRunLength) * 0)
#define PLANAR_CONTROL_BYTE_RUN_LENGTH(_controlByte) (_controlByte & 0x0F)
#define PLANAR_CONTROL_BYTE_RAW_BYTES(_controlByte) ((_controlByte >> 4) & 0x0F)
struct _RDP6_RLE_SEGMENT
{
/**
* controlByte:
* [0-3]: nRunLength
* [4-7]: cRawBytes
*/
BYTE controlByte;
BYTE* rawValues;
};
typedef struct _RDP6_RLE_SEGMENT RDP6_RLE_SEGMENT;
struct _RDP6_RLE_SEGMENTS
{
UINT32 cSegments;
RDP6_RLE_SEGMENT* segments;
};
typedef struct _RDP6_RLE_SEGMENTS RDP6_RLE_SEGMENTS;
#define PLANAR_FORMAT_HEADER_CS (1 << 3)
#define PLANAR_FORMAT_HEADER_RLE (1 << 4)
#define PLANAR_FORMAT_HEADER_NA (1 << 5)
struct _RDP6_BITMAP_STREAM
{
/**
* formatHeader:
* [0-2]: Color Loss Level (CLL)
* [3] : Chroma Subsampling (CS)
* [4] : Run Length Encoding (RLE)
* [5] : No Alpha (NA)
* [6-7]: Reserved
*/
BYTE formatHeader;
};
typedef struct _RDP6_BITMAP_STREAM RDP6_BITMAP_STREAM;
int freerdp_bitmap_planar_decompress(BYTE* srcData, BYTE* dstData, int width, int height, int size);
int freerdp_split_color_planes(BYTE* data, UINT32 format, int width, int height, int scanline, BYTE* planes[5]);
BYTE* freerdp_bitmap_planar_compress_plane_rle(BYTE* plane, int width, int height, BYTE* outPlane, int* dstSize);
BYTE* freerdp_bitmap_planar_delta_encode_plane(BYTE* inPlane, int width, int height, BYTE* outPlane);
int freerdp_bitmap_planar_delta_encode_planes(BYTE* inPlanes[5], int width, int height, BYTE* outPlanes[5]);
#endif /* FREERDP_CODEC_PLANAR_PRIVATE_H */

3
libfreerdp/codec/test/.gitignore vendored Normal file
View File

@ -0,0 +1,3 @@
TestFreeRDPCodec
TestFreeRDPCodec.c

View File

@ -0,0 +1,31 @@
set(MODULE_NAME "TestFreeRDPCodec")
set(MODULE_PREFIX "TEST_FREERDP_CODEC")
set(${MODULE_PREFIX}_DRIVER ${MODULE_NAME}.c)
set(${MODULE_PREFIX}_TESTS
TestFreeRDPCodecPlanar.c)
create_test_sourcelist(${MODULE_PREFIX}_SRCS
${${MODULE_PREFIX}_DRIVER}
${${MODULE_PREFIX}_TESTS})
add_executable(${MODULE_NAME} ${${MODULE_PREFIX}_SRCS})
set_complex_link_libraries(VARIABLE ${MODULE_PREFIX}_LIBS
MONOLITHIC ${MONOLITHIC_BUILD}
MODULE freerdp
MODULES freerdp-codec)
target_link_libraries(${MODULE_NAME} ${${MODULE_PREFIX}_LIBS})
set_target_properties(${MODULE_NAME} PROPERTIES RUNTIME_OUTPUT_DIRECTORY "${TESTING_OUTPUT_DIRECTORY}")
foreach(test ${${MODULE_PREFIX}_TESTS})
get_filename_component(TestName ${test} NAME_WE)
add_test(${TestName} ${TESTING_OUTPUT_DIRECTORY}/${MODULE_NAME} ${TestName})
endforeach()
set_property(TARGET ${MODULE_NAME} PROPERTY FOLDER "FreeRDP/Test")

File diff suppressed because it is too large Load Diff

Binary file not shown.

After

Width:  |  Height:  |  Size: 4.1 KiB

View File

@ -232,36 +232,46 @@ BOOL gcc_read_conference_create_response(wStream* s, rdpSettings* settings)
BYTE number; BYTE number;
/* ConnectData */ /* ConnectData */
per_read_choice(s, &choice); if (!per_read_choice(s, &choice) ||
per_read_object_identifier(s, t124_02_98_oid); !per_read_object_identifier(s, t124_02_98_oid))
return FALSE;
/* ConnectData::connectPDU (OCTET_STRING) */ /* ConnectData::connectPDU (OCTET_STRING) */
per_read_length(s, &length); if (!per_read_length(s, &length))
return FALSE;
/* ConnectGCCPDU */ /* ConnectGCCPDU */
per_read_choice(s, &choice); if (!per_read_choice(s, &choice))
return FALSE;
/* ConferenceCreateResponse::nodeID (UserID) */ /* ConferenceCreateResponse::nodeID (UserID) */
per_read_integer16(s, &nodeID, 1001); if (!per_read_integer16(s, &nodeID, 1001))
return FALSE;
/* ConferenceCreateResponse::tag (INTEGER) */ /* ConferenceCreateResponse::tag (INTEGER) */
per_read_integer(s, &tag); if (!per_read_integer(s, &tag))
return FALSE;
/* ConferenceCreateResponse::result (ENUMERATED) */ /* ConferenceCreateResponse::result (ENUMERATED) */
per_read_enumerated(s, &result, MCS_Result_enum_length); if (!per_read_enumerated(s, &result, MCS_Result_enum_length))
return FALSE;
/* number of UserData sets */ /* number of UserData sets */
per_read_number_of_sets(s, &number); if (!per_read_number_of_sets(s, &number))
return FALSE;
/* UserData::value present + select h221NonStandard (1) */ /* UserData::value present + select h221NonStandard (1) */
per_read_choice(s, &choice); if (!per_read_choice(s, &choice))
return FALSE;
/* h221NonStandard */ /* h221NonStandard */
if (!per_read_octet_string(s, h221_sc_key, 4, 4)) /* h221NonStandard, server-to-client H.221 key, "McDn" */ if (!per_read_octet_string(s, h221_sc_key, 4, 4)) /* h221NonStandard, server-to-client H.221 key, "McDn" */
return FALSE; return FALSE;
/* userData (OCTET_STRING) */ /* userData (OCTET_STRING) */
per_read_length(s, &length); if (!per_read_length(s, &length))
return FALSE;
if (!gcc_read_server_data_blocks(s, settings, length)) if (!gcc_read_server_data_blocks(s, settings, length))
{ {
fprintf(stderr, "gcc_read_conference_create_response: gcc_read_server_data_blocks failed\n"); fprintf(stderr, "gcc_read_conference_create_response: gcc_read_server_data_blocks failed\n");
@ -1125,7 +1135,7 @@ BOOL gcc_read_server_network_data(wStream* s, rdpSettings* settings)
{ {
int i; int i;
UINT16 MCSChannelId; UINT16 MCSChannelId;
UINT16 channelCount; UINT16 channelCount, channelsToTreat;
UINT16 channelId; UINT16 channelId;
if(Stream_GetRemainingLength(s) < 4) if(Stream_GetRemainingLength(s) < 4)
@ -1133,16 +1143,21 @@ BOOL gcc_read_server_network_data(wStream* s, rdpSettings* settings)
Stream_Read_UINT16(s, MCSChannelId); /* MCSChannelId */ Stream_Read_UINT16(s, MCSChannelId); /* MCSChannelId */
Stream_Read_UINT16(s, channelCount); /* channelCount */ Stream_Read_UINT16(s, channelCount); /* channelCount */
channelsToTreat = channelCount;
if (channelCount != settings->ChannelCount) if (channelCount != settings->ChannelCount)
{ {
fprintf(stderr, "requested %d channels, got %d instead\n", fprintf(stderr, "requested %d channels, got %d instead\n",
settings->ChannelCount, channelCount); settings->ChannelCount, channelCount);
// we ensure that the response is not bigger than the request
if (channelCount > settings->ChannelCount)
channelsToTreat = settings->ChannelCount;
} }
if(Stream_GetRemainingLength(s) < channelCount * 2) if(Stream_GetRemainingLength(s) < channelCount * 2)
return FALSE; return FALSE;
for (i = 0; i < channelCount; i++) for (i = 0; i < channelsToTreat; i++)
{ {
Stream_Read_UINT16(s, channelId); /* channelId */ Stream_Read_UINT16(s, channelId); /* channelId */
settings->ChannelDefArray[i].ChannelId = channelId; settings->ChannelDefArray[i].ChannelId = channelId;

View File

@ -1062,8 +1062,17 @@ void transport_free(rdpTransport* transport)
{ {
if (transport->async) if (transport->async)
{ {
assert(!transport->thread); if (transport->stopEvent)
assert(!transport->stopEvent); {
SetEvent(transport->stopEvent);
WaitForSingleObject(transport->thread, INFINITE);
CloseHandle(transport->thread);
CloseHandle(transport->stopEvent);
transport->thread = NULL;
transport->stopEvent = NULL;
}
} }
if (transport->ReceiveBuffer) if (transport->ReceiveBuffer)

View File

@ -111,6 +111,7 @@ BOOL tls_connect(rdpTls* tls)
long options = 0; long options = 0;
int connection_status; int connection_status;
char *hostname; char *hostname;
int port;
tls->ctx = SSL_CTX_new(TLSv1_client_method()); tls->ctx = SSL_CTX_new(TLSv1_client_method());
@ -214,11 +215,17 @@ BOOL tls_connect(rdpTls* tls)
} }
if (tls->settings->GatewayEnabled) if (tls->settings->GatewayEnabled)
{
hostname = tls->settings->GatewayHostname; hostname = tls->settings->GatewayHostname;
port = tls->settings->GatewayPort;
}
else else
{
hostname = tls->settings->ServerHostname; hostname = tls->settings->ServerHostname;
port = tls->settings->ServerPort;
}
if (!tls_verify_certificate(tls, cert, hostname)) if (!tls_verify_certificate(tls, cert, hostname, port))
{ {
fprintf(stderr, "tls_connect: certificate not trusted, aborting.\n"); fprintf(stderr, "tls_connect: certificate not trusted, aborting.\n");
tls_disconnect(tls); tls_disconnect(tls);
@ -568,7 +575,7 @@ BOOL tls_match_hostname(char *pattern, int pattern_length, char *hostname)
return FALSE; return FALSE;
} }
BOOL tls_verify_certificate(rdpTls* tls, CryptoCert cert, char* hostname) BOOL tls_verify_certificate(rdpTls* tls, CryptoCert cert, char* hostname, int port)
{ {
int match; int match;
int index; int index;
@ -651,7 +658,7 @@ BOOL tls_verify_certificate(rdpTls* tls, CryptoCert cert, char* hostname)
if (instance->VerifyX509Certificate) if (instance->VerifyX509Certificate)
{ {
status = instance->VerifyX509Certificate(instance, pemCert, length, 0); status = instance->VerifyX509Certificate(instance, pemCert, length, hostname, port, 0);
} }
fprintf(stderr, "VerifyX509Certificate: (length = %d) status: %d\n%s\n", fprintf(stderr, "VerifyX509Certificate: (length = %d) status: %d\n%s\n",

View File

@ -34,6 +34,7 @@ extern "C" {
#endif #endif
WINPR_API void winpr_HexDump(BYTE* data, int length); WINPR_API void winpr_HexDump(BYTE* data, int length);
WINPR_API void winpr_CArrayDump(BYTE* data, int length, int width);
WINPR_API int wprintfx(const char *fmt, ...); WINPR_API int wprintfx(const char *fmt, ...);
WINPR_API int wvprintfx(const char *fmt, va_list args); WINPR_API int wvprintfx(const char *fmt, va_list args);

View File

@ -60,6 +60,32 @@ void winpr_HexDump(BYTE* data, int length)
} }
} }
void winpr_CArrayDump(BYTE* data, int length, int width)
{
BYTE* p = data;
int i, line, offset = 0;
while (offset < length)
{
line = length - offset;
if (line > width)
line = width;
printf("\t\"");
for (i = 0; i < line; i++)
printf("\\x%02X", p[i]);
printf("\"\n");
offset += line;
p += line;
}
printf("\n");
}
int wvprintfx(const char *fmt, va_list args) int wvprintfx(const char *fmt, va_list args)
{ {
return trio_vprintf(fmt, args); return trio_vprintf(fmt, args);