shadow: reduce resource usage in encoder

This commit is contained in:
Marc-André Moreau 2014-07-16 14:11:37 -04:00
parent 58d83c9c1e
commit 5e33c4899e
5 changed files with 264 additions and 85 deletions

View File

@ -153,7 +153,7 @@ void x11_shadow_validate_region(x11ShadowSubsystem* subsystem, int x, int y, int
{
XRectangle region;
if (!subsystem->use_xfixes)
if (!subsystem->use_xfixes || !subsystem->use_xdamage)
return;
region.x = x;
@ -260,9 +260,14 @@ int x11_shadow_surface_copy(x11ShadowSubsystem* subsystem)
void* x11_shadow_subsystem_thread(x11ShadowSubsystem* subsystem)
{
int fps;
DWORD status;
DWORD nCount;
XEvent xevent;
UINT64 cTime;
DWORD dwTimeout;
DWORD dwInterval;
UINT64 frameTime;
HANDLE events[32];
HANDLE StopEvent;
int x, y, width, height;
@ -274,9 +279,21 @@ void* x11_shadow_subsystem_thread(x11ShadowSubsystem* subsystem)
events[nCount++] = StopEvent;
events[nCount++] = subsystem->event;
fps = 16;
dwInterval = 1000 / fps;
frameTime = GetTickCount64() + dwInterval;
while (1)
{
status = WaitForMultipleObjects(nCount, events, FALSE, INFINITE);
dwTimeout = INFINITE;
if (!subsystem->use_xdamage)
{
cTime = GetTickCount64();
dwTimeout = (cTime > frameTime) ? 0 : frameTime - cTime;
}
status = WaitForMultipleObjects(nCount, events, FALSE, dwTimeout);
if (WaitForSingleObject(StopEvent, 0) == WAIT_OBJECT_0)
{
@ -300,6 +317,17 @@ void* x11_shadow_subsystem_thread(x11ShadowSubsystem* subsystem)
x11_shadow_invalidate_region(subsystem, x, y, width, height);
}
}
if (!subsystem->use_xdamage)
{
if ((status == WAIT_TIMEOUT) || (GetTickCount64() > frameTime))
{
x11_shadow_invalidate_region(subsystem, 0, 0, subsystem->width, subsystem->height);
dwInterval = 1000 / fps;
frameTime += dwInterval;
}
}
}
ExitThread(0);
@ -495,6 +523,8 @@ int x11_shadow_subsystem_init(x11ShadowSubsystem* subsystem)
int i;
int pf_count;
int vi_count;
int nextensions;
char** extensions;
XVisualInfo* vi;
XVisualInfo* vis;
XVisualInfo template;
@ -524,6 +554,25 @@ int x11_shadow_subsystem_init(x11ShadowSubsystem* subsystem)
return -1;
}
extensions = XListExtensions(subsystem->display, &nextensions);
if (!extensions || (nextensions < 0))
return -1;
for (i = 0; i < nextensions; i++)
{
if (strcmp(extensions[i], "Composite") == 0)
subsystem->composite = TRUE;
}
XFreeExtensionList(extensions);
if (subsystem->composite)
subsystem->use_xdamage = FALSE;
if (!subsystem->use_xdamage)
subsystem->use_xfixes = FALSE;
subsystem->xfds = ConnectionNumber(subsystem->display);
subsystem->number = DefaultScreen(subsystem->display);
subsystem->screen = ScreenOfDisplay(subsystem->display, subsystem->number);
@ -706,9 +755,10 @@ x11ShadowSubsystem* x11_shadow_subsystem_new(rdpShadowServer* server)
subsystem->MouseEvent = (pfnShadowMouseEvent) x11_shadow_input_mouse_event;
subsystem->ExtendedMouseEvent = (pfnShadowExtendedMouseEvent) x11_shadow_input_extended_mouse_event;
subsystem->composite = FALSE;
subsystem->use_xshm = TRUE;
subsystem->use_xfixes = TRUE;
subsystem->use_xdamage = TRUE;
subsystem->use_xdamage = FALSE;
subsystem->use_xinerama = TRUE;
return subsystem;

View File

@ -68,6 +68,7 @@ struct x11_shadow_subsystem
Visual* visual;
Display* display;
int scanline_pad;
BOOL composite;
BOOL use_xshm;
BOOL use_xfixes;

View File

@ -248,7 +248,7 @@ int shadow_client_send_surface_bits(rdpShadowClient* client, rdpShadowSurface* s
RFX_RECT rect;
RFX_MESSAGE* messages;
s = encoder->rfx_s;
s = encoder->bs;
rect.x = nXSrc;
rect.y = nYSrc;
@ -288,7 +288,7 @@ int shadow_client_send_surface_bits(rdpShadowClient* client, rdpShadowSurface* s
{
NSC_MESSAGE* messages;
s = encoder->nsc_s;
s = encoder->bs;
messages = nsc_encode_messages(encoder->nsc, pSrcData,
nXSrc, nYSrc, nWidth, nHeight, nSrcStep,
@ -550,12 +550,14 @@ int shadow_client_send_surface_update(rdpShadowClient* client)
rdpSettings* settings;
rdpShadowServer* server;
rdpShadowSurface* surface;
rdpShadowEncoder* encoder;
RECTANGLE_16 surfaceRect;
const RECTANGLE_16* extents;
context = (rdpContext*) client;
settings = context->settings;
server = client->server;
encoder = server->encoder;
surface = client->inLobby ? client->lobby : server->surface;
@ -578,10 +580,17 @@ int shadow_client_send_surface_update(rdpShadowClient* client)
if (settings->RemoteFxCodec || settings->NSCodec)
{
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

@ -58,7 +58,7 @@ int shadow_encoder_create_frame_id(rdpShadowEncoder* encoder)
return (int) frame->frameId;
}
int shadow_encoder_grid_init(rdpShadowEncoder* encoder)
int shadow_encoder_init_grid(rdpShadowEncoder* encoder)
{
int i, j, k;
int tileSize;
@ -92,7 +92,7 @@ int shadow_encoder_grid_init(rdpShadowEncoder* encoder)
return 0;
}
int shadow_encoder_grid_uninit(rdpShadowEncoder* encoder)
int shadow_encoder_uninit_grid(rdpShadowEncoder* encoder)
{
if (encoder->gridBuffer)
{
@ -112,59 +112,145 @@ int shadow_encoder_grid_uninit(rdpShadowEncoder* encoder)
return 0;
}
int shadow_encoder_init(rdpShadowEncoder* encoder)
int shadow_encoder_init_rfx(rdpShadowEncoder* encoder)
{
DWORD planarFlags;
if (!encoder->rfx)
encoder->rfx = rfx_context_new(TRUE);
encoder->scanline = (encoder->width + (encoder->width % 4)) * 4;
encoder->data = (BYTE*) malloc(encoder->scanline * encoder->height);
if (!encoder->data)
if (!encoder->rfx)
return -1;
encoder->maxTileWidth = 64;
encoder->maxTileHeight = 64;
encoder->bs = Stream_New(NULL, encoder->maxTileWidth * encoder->maxTileHeight * 4);
encoder->bts = Stream_New(NULL, encoder->maxTileWidth * encoder->maxTileHeight * 4);
planarFlags = PLANAR_FORMAT_HEADER_NA;
planarFlags |= PLANAR_FORMAT_HEADER_RLE;
encoder->planar = freerdp_bitmap_planar_context_new(planarFlags,
encoder->maxTileWidth, encoder->maxTileHeight);
encoder->rfx = rfx_context_new(TRUE);
encoder->rfx_s = Stream_New(NULL, encoder->maxTileWidth * encoder->maxTileHeight * 4);
encoder->rfx->mode = RLGR3;
encoder->rfx->width = encoder->width;
encoder->rfx->height = encoder->height;
encoder->nsc = nsc_context_new();
encoder->nsc_s = Stream_New(NULL, encoder->maxTileWidth * encoder->maxTileHeight * 4);
rfx_context_set_pixel_format(encoder->rfx, RDP_PIXEL_FORMAT_B8G8R8A8);
nsc_context_set_pixel_format(encoder->nsc, RDP_PIXEL_FORMAT_B8G8R8A8);
shadow_encoder_grid_init(encoder);
if (!encoder->frameList)
{
encoder->fps = 16;
encoder->maxFps = 32;
encoder->frameId = 0;
encoder->frameAck = TRUE;
encoder->frameList = ListDictionary_New(TRUE);
}
encoder->fps = 10;
encoder->maxFps = 32;
encoder->frameId = 0;
encoder->frameAck = TRUE;
encoder->frameList = ListDictionary_New(TRUE);
encoder->codecs |= SHADOW_CODEC_REMOTEFX;
return 1;
}
int shadow_encoder_uninit(rdpShadowEncoder* encoder)
int shadow_encoder_init_nsc(rdpShadowEncoder* encoder)
{
if (encoder->bs)
if (!encoder->nsc)
encoder->nsc = nsc_context_new();
if (!encoder->nsc)
return -1;
nsc_context_set_pixel_format(encoder->nsc, RDP_PIXEL_FORMAT_B8G8R8A8);
if (!encoder->frameList)
{
Stream_Free(encoder->bs, TRUE);
encoder->bs = NULL;
encoder->fps = 16;
encoder->maxFps = 32;
encoder->frameId = 0;
encoder->frameAck = TRUE;
encoder->frameList = ListDictionary_New(TRUE);
}
encoder->codecs |= SHADOW_CODEC_NSCODEC;
return 1;
}
int shadow_encoder_init_bitmap(rdpShadowEncoder* encoder)
{
DWORD planarFlags;
planarFlags = PLANAR_FORMAT_HEADER_NA;
planarFlags |= PLANAR_FORMAT_HEADER_RLE;
if (!encoder->planar)
{
encoder->planar = freerdp_bitmap_planar_context_new(planarFlags,
encoder->maxTileWidth, encoder->maxTileHeight);
}
if (!encoder->planar)
return -1;
if (!encoder->bts)
encoder->bts = Stream_New(NULL, encoder->maxTileWidth * encoder->maxTileHeight * 4);
if (!encoder->bts)
return -1;
encoder->codecs |= SHADOW_CODEC_BITMAP;
return 1;
}
int shadow_encoder_init(rdpShadowEncoder* encoder)
{
encoder->maxTileWidth = 64;
encoder->maxTileHeight = 64;
shadow_encoder_init_grid(encoder);
if (!encoder->bs)
encoder->bs = Stream_New(NULL, encoder->maxTileWidth * encoder->maxTileHeight * 4);
if (!encoder->bs)
return -1;
return 1;
}
int shadow_encoder_uninit_rfx(rdpShadowEncoder* encoder)
{
if (encoder->rfx)
{
rfx_context_free(encoder->rfx);
encoder->rfx = NULL;
}
if (encoder->frameList)
{
ListDictionary_Free(encoder->frameList);
encoder->frameList = NULL;
}
encoder->codecs &= ~SHADOW_CODEC_REMOTEFX;
return 1;
}
int shadow_encoder_uninit_nsc(rdpShadowEncoder* encoder)
{
if (encoder->nsc)
{
nsc_context_free(encoder->nsc);
encoder->nsc = NULL;
}
if (encoder->frameList)
{
ListDictionary_Free(encoder->frameList);
encoder->frameList = NULL;
}
encoder->codecs &= ~SHADOW_CODEC_NSCODEC;
return 1;
}
int shadow_encoder_uninit_bitmap(rdpShadowEncoder* encoder)
{
if (encoder->planar)
{
freerdp_bitmap_planar_context_free(encoder->planar);
encoder->planar = NULL;
}
if (encoder->bts)
@ -173,42 +259,34 @@ int shadow_encoder_uninit(rdpShadowEncoder* encoder)
encoder->bts = NULL;
}
if (encoder->rfx_s)
encoder->codecs &= ~SHADOW_CODEC_BITMAP;
return 1;
}
int shadow_encoder_uninit(rdpShadowEncoder* encoder)
{
shadow_encoder_uninit_grid(encoder);
if (encoder->bs)
{
Stream_Free(encoder->rfx_s, TRUE);
encoder->rfx_s = NULL;
Stream_Free(encoder->bs, TRUE);
encoder->bs = NULL;
}
if (encoder->rfx)
if (encoder->codecs & SHADOW_CODEC_REMOTEFX)
{
rfx_context_free(encoder->rfx);
encoder->rfx = NULL;
shadow_encoder_uninit_rfx(encoder);
}
if (encoder->nsc_s)
if (encoder->codecs & SHADOW_CODEC_NSCODEC)
{
Stream_Free(encoder->nsc_s, TRUE);
encoder->nsc_s = NULL;
shadow_encoder_uninit_nsc(encoder);
}
if (encoder->nsc)
if (encoder->codecs & SHADOW_CODEC_BITMAP)
{
nsc_context_free(encoder->nsc);
encoder->nsc = NULL;
}
if (encoder->planar)
{
freerdp_bitmap_planar_context_free(encoder->planar);
encoder->planar = NULL;
}
shadow_encoder_grid_uninit(encoder);
if (encoder->frameList)
{
ListDictionary_Free(encoder->frameList);
encoder->frameList = NULL;
shadow_encoder_uninit_bitmap(encoder);
}
return 1;
@ -216,10 +294,56 @@ int shadow_encoder_uninit(rdpShadowEncoder* encoder)
int shadow_encoder_reset(rdpShadowEncoder* encoder)
{
if (shadow_encoder_uninit(encoder) < 0)
int status;
UINT32 codecs = encoder->codecs;
status = shadow_encoder_uninit(encoder);
if (status < 0)
return -1;
return shadow_encoder_init(encoder);
status = shadow_encoder_init(encoder);
if (status < 0)
return -1;
status = shadow_encoder_prepare(encoder, codecs);
if (status < 0)
return -1;
return 1;
}
int shadow_encoder_prepare(rdpShadowEncoder* encoder, UINT32 codecs)
{
int status;
if ((codecs & SHADOW_CODEC_REMOTEFX) && !(encoder->codecs & SHADOW_CODEC_REMOTEFX))
{
status = shadow_encoder_init_rfx(encoder);
if (status < 0)
return -1;
}
if ((codecs & SHADOW_CODEC_NSCODEC) && !(encoder->codecs & SHADOW_CODEC_NSCODEC))
{
status = shadow_encoder_init_nsc(encoder);
if (status < 0)
return -1;
}
if ((codecs & SHADOW_CODEC_BITMAP) && !(encoder->codecs & SHADOW_CODEC_BITMAP))
{
status = shadow_encoder_init_bitmap(encoder);
if (status < 0)
return -1;
}
return 1;
}
rdpShadowEncoder* shadow_encoder_new(rdpShadowServer* server)
@ -236,9 +360,6 @@ rdpShadowEncoder* shadow_encoder_new(rdpShadowServer* server)
encoder->width = server->screen->width;
encoder->height = server->screen->height;
encoder->bitsPerPixel = 32;
encoder->bytesPerPixel = 4;
if (shadow_encoder_init(encoder) < 0)
return NULL;

View File

@ -29,17 +29,17 @@
#include <freerdp/server/shadow.h>
#define SHADOW_CODEC_REMOTEFX 1
#define SHADOW_CODEC_NSCODEC 2
#define SHADOW_CODEC_BITMAP 4
struct rdp_shadow_encoder
{
rdpShadowServer* server;
BYTE* data;
int width;
int height;
int scanline;
UINT32 bitsPerPixel;
UINT32 bytesPerPixel;
UINT32 codecs;
BYTE** grid;
int gridWidth;
@ -48,14 +48,11 @@ struct rdp_shadow_encoder
int maxTileWidth;
int maxTileHeight;
wStream* rfx_s;
RFX_CONTEXT* rfx;
wStream* nsc_s;
NSC_CONTEXT* nsc;
wStream* bs;
wStream* bts;
RFX_CONTEXT* rfx;
NSC_CONTEXT* nsc;
BITMAP_PLANAR_CONTEXT* planar;
int fps;
@ -70,6 +67,7 @@ extern "C" {
#endif
int shadow_encoder_reset(rdpShadowEncoder* encoder);
int shadow_encoder_prepare(rdpShadowEncoder* encoder, UINT32 codecs);
int shadow_encoder_create_frame_id(rdpShadowEncoder* encoder);
rdpShadowEncoder* shadow_encoder_new(rdpShadowServer* server);