libfreerdp-codec: improve compressor interfaces

This commit is contained in:
Marc-André Moreau 2014-09-20 15:25:33 -04:00
parent d6250b1aec
commit 45b9a5454e
8 changed files with 158 additions and 101 deletions

View File

@ -34,11 +34,16 @@ struct _BITMAP_INTERLEAVED_CONTEXT
UINT32 TempSize;
BYTE* TempBuffer;
wStream* bts;
};
FREERDP_API int interleaved_decompress(BITMAP_INTERLEAVED_CONTEXT* interleaved, BYTE* pSrcData, UINT32 SrcSize, int bpp,
BYTE** ppDstData, DWORD DstFormat, int nDstStep, int nXDst, int nYDst, int nWidth, int nHeight, BYTE* palette);
FREERDP_API int interleaved_compress(BITMAP_INTERLEAVED_CONTEXT* interleaved, BYTE* pDstData, UINT32* pDstSize,
int nWidth, int nHeight, BYTE* pSrcData, DWORD SrcFormat, int nSrcStep, int nXSrc, int nYSrc, BYTE* palette, int bpp);
FREERDP_API int bitmap_interleaved_context_reset(BITMAP_INTERLEAVED_CONTEXT* interleaved);
FREERDP_API BITMAP_INTERLEAVED_CONTEXT* bitmap_interleaved_context_new(BOOL Compressor);

View File

@ -103,7 +103,7 @@ FREERDP_API BYTE* freerdp_bitmap_planar_delta_encode_plane(BYTE* inPlane, int wi
FREERDP_API int freerdp_bitmap_planar_delta_encode_planes(BYTE* inPlanes[4], int width, int height, BYTE* outPlanes[4]);
FREERDP_API BYTE* freerdp_bitmap_compress_planar(BITMAP_PLANAR_CONTEXT* context, BYTE* data, UINT32 format,
int width, int height, int scanline, BYTE* dstData, int* dstSize);
int width, int height, int scanline, BYTE* dstData, int* pDstSize);
FREERDP_API int freerdp_bitmap_planar_context_reset(BITMAP_PLANAR_CONTEXT* context);

View File

@ -347,6 +347,57 @@ int interleaved_decompress(BITMAP_INTERLEAVED_CONTEXT* interleaved, BYTE* pSrcDa
return 1;
}
int interleaved_compress(BITMAP_INTERLEAVED_CONTEXT* interleaved, BYTE* pDstData, UINT32* pDstSize,
int nWidth, int nHeight, BYTE* pSrcData, DWORD SrcFormat, int nSrcStep, int nXSrc, int nYSrc, BYTE* palette, int bpp)
{
int status;
wStream* s;
UINT32 DstFormat = 0;
int maxSize = 64 * 64 * 4;
if (nWidth % 4)
{
fprintf(stderr, "interleaved_compress: width is not a multiple of 4\n");
return -1;
}
if ((nWidth > 64) || (nHeight > 64))
{
fprintf(stderr, "interleaved_compress: width (%d) or height (%d) is greater than 64\n", nWidth, nHeight);
return -1;
}
if (bpp == 24)
DstFormat = PIXEL_FORMAT_RGB24;
else if (bpp == 16)
DstFormat = PIXEL_FORMAT_RGB16;
else if (bpp == 15)
DstFormat = PIXEL_FORMAT_RGB15;
else if (bpp == 8)
DstFormat = PIXEL_FORMAT_RGB8;
if (!DstFormat)
return -1;
status = freerdp_image_copy(interleaved->TempBuffer, DstFormat, -1, 0, 0, nWidth, nHeight,
pSrcData, SrcFormat, nSrcStep, nXSrc, nYSrc, palette);
s = Stream_New(pDstData, maxSize);
if (!s)
return -1;
status = freerdp_bitmap_compress((char*) interleaved->TempBuffer, nWidth, nHeight,
s, bpp, maxSize, nHeight - 1, interleaved->bts, 0);
Stream_SealLength(s);
*pDstSize = (UINT32) Stream_Length(s);
Stream_Free(s, FALSE);
return status;
}
int bitmap_interleaved_context_reset(BITMAP_INTERLEAVED_CONTEXT* interleaved)
{
return 1;
@ -360,8 +411,9 @@ BITMAP_INTERLEAVED_CONTEXT* bitmap_interleaved_context_new(BOOL Compressor)
if (interleaved)
{
interleaved->TempSize = 64 * 64 * 3;
interleaved->TempSize = 64 * 64 * 4;
interleaved->TempBuffer = _aligned_malloc(interleaved->TempSize, 16);
interleaved->bts = Stream_New(NULL, interleaved->TempSize);
}
return interleaved;
@ -373,6 +425,7 @@ void bitmap_interleaved_context_free(BITMAP_INTERLEAVED_CONTEXT* interleaved)
return;
_aligned_free(interleaved->TempBuffer);
Stream_Free(interleaved->bts, TRUE);
free(interleaved);
}

View File

@ -406,8 +406,10 @@ NSC_MESSAGE* nsc_encode_messages(NSC_CONTEXT* context, BYTE* data, int x, int y,
maxDataSize -= 1024; /* reserve enough space for headers */
messages = (NSC_MESSAGE*) malloc(sizeof(NSC_MESSAGE) * (*numMessages));
ZeroMemory(messages, sizeof(NSC_MESSAGE) * (*numMessages));
messages = (NSC_MESSAGE*) calloc(*numMessages, sizeof(NSC_MESSAGE));
if (!messages)
return NULL;
for (i = 0; i < rows; i++)
{

View File

@ -1001,7 +1001,7 @@ int freerdp_bitmap_planar_delta_encode_planes(BYTE* inPlanes[4], int width, int
}
BYTE* freerdp_bitmap_compress_planar(BITMAP_PLANAR_CONTEXT* context, BYTE* data, UINT32 format,
int width, int height, int scanline, BYTE* dstData, int* dstSize)
int width, int height, int scanline, BYTE* dstData, int* pDstSize)
{
int size;
BYTE* dstp;
@ -1064,7 +1064,7 @@ BYTE* freerdp_bitmap_compress_planar(BITMAP_PLANAR_CONTEXT* context, BYTE* data,
size++;
dstData = malloc(size);
*dstSize = size;
*pDstSize = size;
}
dstp = dstData;
@ -1136,7 +1136,7 @@ BYTE* freerdp_bitmap_compress_planar(BITMAP_PLANAR_CONTEXT* context, BYTE* data,
}
size = (dstp - dstData);
*dstSize = size;
*pDstSize = size;
return dstData;
}

View File

@ -51,6 +51,10 @@ void shadow_client_context_new(freerdp_peer* peer, rdpShadowClient* client)
settings->FrameMarkerCommandEnabled = TRUE;
settings->SurfaceFrameMarkerEnabled = TRUE;
settings->DrawAllowSkipAlpha = TRUE;
settings->DrawAllowColorSubsampling = TRUE;
settings->DrawAllowDynamicColorFidelity = TRUE;
settings->RdpSecurity = TRUE;
settings->TlsSecurity = TRUE;
settings->NlaSecurity = FALSE;
@ -329,11 +333,13 @@ int shadow_client_send_surface_bits(rdpShadowClient* client, rdpShadowSurface* s
if (encoder->frameAck)
frameId = (UINT32) shadow_encoder_create_frame_id(encoder);
if (settings->RemoteFxCodec)
if (settings->RemoteFxCodec && 0)
{
RFX_RECT rect;
RFX_MESSAGE* messages;
shadow_encoder_prepare(encoder, FREERDP_CODEC_REMOTEFX);
s = encoder->bs;
rect.x = nXSrc;
@ -380,6 +386,8 @@ int shadow_client_send_surface_bits(rdpShadowClient* client, rdpShadowSurface* s
{
NSC_MESSAGE* messages;
shadow_encoder_prepare(encoder, FREERDP_CODEC_NSCODEC);
s = encoder->bs;
messages = nsc_encode_messages(encoder->nsc, pSrcData,
@ -426,12 +434,10 @@ int shadow_client_send_bitmap_update(rdpShadowClient* client, rdpShadowSurface*
BYTE* data;
BYTE* buffer;
int i, j, k;
wStream* s;
wStream* ts;
int e, lines;
int rows, cols;
int nSrcStep;
BYTE* pSrcData;
UINT32 DstSize;
rdpUpdate* update;
rdpContext* context;
rdpSettings* settings;
@ -449,6 +455,11 @@ int shadow_client_send_bitmap_update(rdpShadowClient* client, rdpShadowSurface*
server = client->server;
encoder = client->encoder;
if (settings->ColorDepth < 32)
shadow_encoder_prepare(encoder, FREERDP_CODEC_INTERLEAVED);
else
shadow_encoder_prepare(encoder, FREERDP_CODEC_PLANAR);
pSrcData = surface->data;
nSrcStep = surface->scanline;
@ -537,33 +548,41 @@ int shadow_client_send_bitmap_update(rdpShadowClient* client, rdpShadowSurface*
if (((nWidth * nHeight) > 0) && (nWidth >= 4) && (nHeight >= 4))
{
UINT32 srcFormat = PIXEL_FORMAT_RGB32;
int nXSubSrc;
int nYSubSrc;
UINT32 SrcFormat;
e = nWidth % 4;
nXSubSrc = bitmapData[k].destLeft;
nYSubSrc = bitmapData[k].destTop;
if (e != 0)
e = 4 - e;
SrcFormat = PIXEL_FORMAT_RGB32;
s = encoder->bs;
ts = encoder->bts;
if (settings->ColorDepth < 32)
{
int bitsPerPixel = settings->ColorDepth;
int bytesPerPixel = (bitsPerPixel + 7) / 8;
Stream_SetPosition(s, 0);
Stream_SetPosition(ts, 0);
DstSize = 64 * 64 * 4;
buffer = encoder->grid[k];
data = surface->data;
data = &data[(bitmapData[k].destTop * nSrcStep) +
(bitmapData[k].destLeft * 4)];
interleaved_compress(encoder->interleaved, buffer, &DstSize, nWidth, nHeight,
pSrcData, SrcFormat, nSrcStep, nXSubSrc, nYSubSrc, NULL, bitsPerPixel);
srcFormat = PIXEL_FORMAT_RGB32;
if (settings->ColorDepth > 24)
bitmapData[k].bitmapDataStream = buffer;
bitmapData[k].bitmapLength = DstSize;
bitmapData[k].bitsPerPixel = bitsPerPixel;
bitmapData[k].cbScanWidth = nWidth * bytesPerPixel;
bitmapData[k].cbUncompressedSize = nWidth * nHeight * bytesPerPixel;
}
else
{
int dstSize;
buffer = encoder->grid[k];
data = &pSrcData[(bitmapData[k].destTop * nSrcStep) + (bitmapData[k].destLeft * 4)];
buffer = freerdp_bitmap_compress_planar(encoder->planar,
data, srcFormat, nWidth, nHeight, nSrcStep, buffer, &dstSize);
data, SrcFormat, nWidth, nHeight, nSrcStep, buffer, &dstSize);
bitmapData[k].bitmapDataStream = buffer;
bitmapData[k].bitmapLength = dstSize;
@ -572,43 +591,6 @@ int shadow_client_send_bitmap_update(rdpShadowClient* client, rdpShadowSurface*
bitmapData[k].cbScanWidth = nWidth * 4;
bitmapData[k].cbUncompressedSize = nWidth * nHeight * 4;
}
else
{
int bytesPerPixel = 2;
UINT32 dstFormat = PIXEL_FORMAT_RGB16;
if (settings->ColorDepth == 15)
{
bytesPerPixel = 2;
dstFormat = PIXEL_FORMAT_RGB15;
}
else if (settings->ColorDepth == 24)
{
bytesPerPixel = 3;
dstFormat = PIXEL_FORMAT_XRGB32;
}
buffer = encoder->grid[k];
freerdp_image_copy(buffer, dstFormat, -1, 0, 0, nWidth, nHeight,
data, srcFormat, nSrcStep, 0, 0, NULL);
lines = freerdp_bitmap_compress((char*) buffer, nWidth, nHeight, s,
settings->ColorDepth, 64 * 64 * 4, nHeight - 1, ts, e);
Stream_SealLength(s);
bitmapData[k].bitmapDataStream = Stream_Buffer(s);
bitmapData[k].bitmapLength = Stream_Length(s);
buffer = encoder->grid[k];
CopyMemory(buffer, bitmapData[k].bitmapDataStream, bitmapData[k].bitmapLength);
bitmapData[k].bitmapDataStream = buffer;
bitmapData[k].bitsPerPixel = settings->ColorDepth;
bitmapData[k].cbScanWidth = nWidth * bytesPerPixel;
bitmapData[k].cbUncompressedSize = nWidth * nHeight * bytesPerPixel;
}
bitmapData[k].cbCompFirstRowSize = 0;
bitmapData[k].cbCompMainBodySize = bitmapData[k].bitmapLength;
@ -684,19 +666,13 @@ int shadow_client_send_surface_update(rdpShadowClient* client)
//WLog_INFO(TAG, "shadow_client_send_surface_update: x: %d y: %d width: %d height: %d right: %d bottom: %d",
// nXSrc, nYSrc, nWidth, nHeight, nXSrc + nWidth, nYSrc + nHeight);
if (settings->RemoteFxCodec || settings->NSCodec)
//if (settings->RemoteFxCodec || settings->NSCodec)
if (0)
{
if (settings->RemoteFxCodec)
shadow_encoder_prepare(encoder, SHADOW_CODEC_REMOTEFX);
else if (settings->NSCodec)
shadow_encoder_prepare(encoder, SHADOW_CODEC_NSCODEC);
status = shadow_client_send_surface_bits(client, surface, nXSrc, nYSrc, nWidth, nHeight);
}
else
{
shadow_encoder_prepare(encoder, SHADOW_CODEC_BITMAP);
status = shadow_client_send_bitmap_update(client, surface, nXSrc, nYSrc, nWidth, nHeight);
}

View File

@ -135,7 +135,7 @@ int shadow_encoder_init_rfx(rdpShadowEncoder* encoder)
encoder->frameList = ListDictionary_New(TRUE);
}
encoder->codecs |= SHADOW_CODEC_REMOTEFX;
encoder->codecs |= FREERDP_CODEC_REMOTEFX;
return 1;
}
@ -159,12 +159,12 @@ int shadow_encoder_init_nsc(rdpShadowEncoder* encoder)
encoder->frameList = ListDictionary_New(TRUE);
}
encoder->codecs |= SHADOW_CODEC_NSCODEC;
encoder->codecs |= FREERDP_CODEC_NSCODEC;
return 1;
}
int shadow_encoder_init_bitmap(rdpShadowEncoder* encoder)
int shadow_encoder_init_planar(rdpShadowEncoder* encoder)
{
DWORD planarFlags = 0;
rdpContext* context = (rdpContext*) encoder->client;
@ -184,13 +184,20 @@ int shadow_encoder_init_bitmap(rdpShadowEncoder* encoder)
if (!encoder->planar)
return -1;
if (!encoder->bts)
encoder->bts = Stream_New(NULL, encoder->maxTileWidth * encoder->maxTileHeight * 4);
encoder->codecs |= FREERDP_CODEC_PLANAR;
if (!encoder->bts)
return 1;
}
int shadow_encoder_init_interleaved(rdpShadowEncoder* encoder)
{
if (!encoder->interleaved)
encoder->interleaved = bitmap_interleaved_context_new(TRUE);
if (!encoder->interleaved)
return -1;
encoder->codecs |= SHADOW_CODEC_BITMAP;
encoder->codecs |= FREERDP_CODEC_INTERLEAVED;
return 1;
}
@ -225,7 +232,7 @@ int shadow_encoder_uninit_rfx(rdpShadowEncoder* encoder)
encoder->frameList = NULL;
}
encoder->codecs &= ~SHADOW_CODEC_REMOTEFX;
encoder->codecs &= ~FREERDP_CODEC_REMOTEFX;
return 1;
}
@ -244,12 +251,12 @@ int shadow_encoder_uninit_nsc(rdpShadowEncoder* encoder)
encoder->frameList = NULL;
}
encoder->codecs &= ~SHADOW_CODEC_NSCODEC;
encoder->codecs &= ~FREERDP_CODEC_NSCODEC;
return 1;
}
int shadow_encoder_uninit_bitmap(rdpShadowEncoder* encoder)
int shadow_encoder_uninit_planar(rdpShadowEncoder* encoder)
{
if (encoder->planar)
{
@ -257,13 +264,20 @@ int shadow_encoder_uninit_bitmap(rdpShadowEncoder* encoder)
encoder->planar = NULL;
}
if (encoder->bts)
encoder->codecs &= ~FREERDP_CODEC_PLANAR;
return 1;
}
int shadow_encoder_uninit_interleaved(rdpShadowEncoder* encoder)
{
if (encoder->interleaved)
{
Stream_Free(encoder->bts, TRUE);
encoder->bts = NULL;
bitmap_interleaved_context_free(encoder->interleaved);
encoder->interleaved = NULL;
}
encoder->codecs &= ~SHADOW_CODEC_BITMAP;
encoder->codecs &= ~FREERDP_CODEC_INTERLEAVED;
return 1;
}
@ -278,19 +292,24 @@ int shadow_encoder_uninit(rdpShadowEncoder* encoder)
encoder->bs = NULL;
}
if (encoder->codecs & SHADOW_CODEC_REMOTEFX)
if (encoder->codecs & FREERDP_CODEC_REMOTEFX)
{
shadow_encoder_uninit_rfx(encoder);
}
if (encoder->codecs & SHADOW_CODEC_NSCODEC)
if (encoder->codecs & FREERDP_CODEC_NSCODEC)
{
shadow_encoder_uninit_nsc(encoder);
}
if (encoder->codecs & SHADOW_CODEC_BITMAP)
if (encoder->codecs & FREERDP_CODEC_PLANAR)
{
shadow_encoder_uninit_bitmap(encoder);
shadow_encoder_uninit_planar(encoder);
}
if (encoder->codecs & FREERDP_CODEC_INTERLEAVED)
{
shadow_encoder_uninit_interleaved(encoder);
}
return 1;
@ -323,7 +342,7 @@ int shadow_encoder_prepare(rdpShadowEncoder* encoder, UINT32 codecs)
{
int status;
if ((codecs & SHADOW_CODEC_REMOTEFX) && !(encoder->codecs & SHADOW_CODEC_REMOTEFX))
if ((codecs & FREERDP_CODEC_REMOTEFX) && !(encoder->codecs & FREERDP_CODEC_REMOTEFX))
{
status = shadow_encoder_init_rfx(encoder);
@ -331,7 +350,7 @@ int shadow_encoder_prepare(rdpShadowEncoder* encoder, UINT32 codecs)
return -1;
}
if ((codecs & SHADOW_CODEC_NSCODEC) && !(encoder->codecs & SHADOW_CODEC_NSCODEC))
if ((codecs & FREERDP_CODEC_NSCODEC) && !(encoder->codecs & FREERDP_CODEC_NSCODEC))
{
status = shadow_encoder_init_nsc(encoder);
@ -339,9 +358,17 @@ int shadow_encoder_prepare(rdpShadowEncoder* encoder, UINT32 codecs)
return -1;
}
if ((codecs & SHADOW_CODEC_BITMAP) && !(encoder->codecs & SHADOW_CODEC_BITMAP))
if ((codecs & FREERDP_CODEC_PLANAR) && !(encoder->codecs & FREERDP_CODEC_PLANAR))
{
status = shadow_encoder_init_bitmap(encoder);
status = shadow_encoder_init_planar(encoder);
if (status < 0)
return -1;
}
if ((codecs & FREERDP_CODEC_INTERLEAVED) && !(encoder->codecs & FREERDP_CODEC_INTERLEAVED))
{
status = shadow_encoder_init_interleaved(encoder);
if (status < 0)
return -1;

View File

@ -23,16 +23,10 @@
#include <winpr/stream.h>
#include <freerdp/freerdp.h>
#include <freerdp/codec/rfx.h>
#include <freerdp/codec/nsc.h>
#include <freerdp/codec/bitmap.h>
#include <freerdp/codecs.h>
#include <freerdp/server/shadow.h>
#define SHADOW_CODEC_REMOTEFX 1
#define SHADOW_CODEC_NSCODEC 2
#define SHADOW_CODEC_BITMAP 4
struct rdp_shadow_encoder
{
rdpShadowClient* client;
@ -50,11 +44,11 @@ struct rdp_shadow_encoder
int maxTileHeight;
wStream* bs;
wStream* bts;
RFX_CONTEXT* rfx;
NSC_CONTEXT* nsc;
BITMAP_PLANAR_CONTEXT* planar;
BITMAP_INTERLEAVED_CONTEXT* interleaved;
int fps;
int maxFps;