mfreerdp-server: got rfx working at 1fps

This commit is contained in:
C-o-r-E 2012-11-15 12:16:10 -05:00
parent 05cd1dc600
commit b33b0380b0
3 changed files with 206 additions and 18 deletions

View File

@ -18,6 +18,7 @@
set(MODULE_NAME "mfreerdp-server")
set(MODULE_PREFIX "FREERDP_SERVER_MAC")
FIND_LIBRARY(CORE_VIDEO CoreVideo)
FIND_LIBRARY(CORE_GRAPHICS CoreGraphics)
FIND_LIBRARY(APP_SERVICES ApplicationServices)
@ -44,6 +45,7 @@ add_executable(${MODULE_NAME} ${${MODULE_PREFIX}_SRCS})
set(${MODULE_PREFIX}_LIBS ${${MODULE_PREFIX}_LIBS}
freerdp-server
${CORE_VIDEO}
${CORE_GRAPHICS}
${APP_SERVICES})

View File

@ -55,6 +55,11 @@
#include <mach/mach.h>
#include <dispatch/dispatch.h>
#include "OpenGL/OpenGL.h"
#include "OpenGL/gl.h"
#include "CoreVideo/CoreVideo.h"
//refactor these
int info_last_sec = 0;
int info_last_nsec = 0;
@ -64,6 +69,62 @@ dispatch_queue_t info_queue;
mfEventQueue* info_event_queue;
CGLContextObj glContext;
CGContextRef bmp;
CGImageRef img;
//UINT32 servscreen_width;
//UINT32 servscreen_height;
//UINT32 bitsPerPixel;
//int cnt = 0;
/*
* perform an in-place swap from Quadrant 1 to Quadrant III format
* (upside-down PostScript/GL to right side up QD/CG raster format)
* We do this in-place, which requires more copying, but will touch
* only half the pages. (Display grabs are BIG!)
*
* Pixel reformatting may optionally be done here if needed.
*/
static void swizzleBitmap(void * data, int rowBytes, int height)
{
int top, bottom;
void * buffer;
void * topP;
void * bottomP;
void * base;
top = 0;
bottom = height - 1;
base = data;
buffer = malloc(rowBytes);
while ( top < bottom )
{
topP = (void *)((top * rowBytes) + (intptr_t)base);
bottomP = (void *)((bottom * rowBytes) + (intptr_t)base);
/*
* Save and swap scanlines.
*
* This code does a simple in-place exchange with a temp buffer.
* If you need to reformat the pixels, replace the first two bcopy()
* calls with your own custom pixel reformatter.
*/
bcopy( topP, buffer, rowBytes );
bcopy( bottomP, topP, rowBytes );
bcopy( buffer, bottomP, rowBytes );
++top;
--bottom;
}
free( buffer );
}
BOOL mf_peer_get_fds(freerdp_peer* client, void** rfds, int* rcount)
{
if (info_event_queue->pipe_fd[0] == -1)
@ -100,6 +161,8 @@ BOOL mf_peer_check_fds(freerdp_peer* client)
event = mf_event_pop(info_event_queue);
printf("Tick\n");
mf_peer_rfx_update(client);
/*invalid_region = xfp->hdc->hwnd->invalid;
@ -124,27 +187,129 @@ BOOL mf_peer_check_fds(freerdp_peer* client)
void mf_peer_rfx_update(freerdp_peer* client)
{
//limit rate
/*
clock_serv_t cclock;
mach_timespec_t mts;
host_get_clock_service(mach_host_self(), CALENDAR_CLOCK, &cclock);
clock_get_time(cclock, &mts);
mach_port_deallocate(mach_task_self(), cclock);
//check
/*if (servscreen_height * servscreen_width == 0)
return;
if ( (mts.tv_sec - info_last_sec > 0) && (mts.tv_nsec - info_last_nsec > 500000000) ) {
printf("rfx_update\n");
info_last_nsec = mts.tv_nsec;
info_last_sec = mts.tv_sec;
}
if(cnt++ < 10)
return;
*/
//capture entire screen
int bytewidth;
CGImageRef image = CGDisplayCreateImage(kCGDirectMainDisplay); // Main screenshot capture call
CGSize frameSize = CGSizeMake(CGImageGetWidth(image), CGImageGetHeight(image)); // Get screenshot bounds
CFDictionaryRef opts;
long ImageCompatibility;
long BitmapContextCompatibility;
void * keys[3];
keys[0] = (void *) kCVPixelBufferCGImageCompatibilityKey;
keys[1] = (void *) kCVPixelBufferCGBitmapContextCompatibilityKey;
keys[2] = NULL;
void * values[3];
values[0] = (void *) &ImageCompatibility;
values[1] = (void *) &BitmapContextCompatibility;
values[2] = NULL;
opts = CFDictionaryCreate(kCFAllocatorDefault, (const void **) keys, (const void **) values, 2, NULL, NULL);
if (opts == NULL)
{
printf("failed to create dictionary\n");
//return 1;
}
CVPixelBufferRef pxbuffer = NULL;
CVReturn status = CVPixelBufferCreate(kCFAllocatorDefault, frameSize.width,
frameSize.height, kCVPixelFormatType_32ARGB, opts,
&pxbuffer);
if (status != kCVReturnSuccess)
{
printf("Failed to create pixel buffer! \n");
//return 1;
}
CFRelease(opts);
CVPixelBufferLockBaseAddress(pxbuffer, 0);
void *pxdata = CVPixelBufferGetBaseAddress(pxbuffer);
CGColorSpaceRef rgbColorSpace = CGColorSpaceCreateDeviceRGB();
CGContextRef context = CGBitmapContextCreate(pxdata, frameSize.width,
frameSize.height, 8, 4*frameSize.width, rgbColorSpace,
kCGImageAlphaNoneSkipLast);
CGContextDrawImage(context, CGRectMake(0, 0, CGImageGetWidth(image),
CGImageGetHeight(image)), image);
bytewidth = frameSize.width * 4; // Assume 4 bytes/pixel for now
bytewidth = (bytewidth + 3) & ~3; // Align to 4 bytes
//swizzleBitmap(pxdata, bytewidth, frameSize.height); // Solution for ARGB madness
//encode
STREAM* s;
RFX_RECT rect;
rdpUpdate* update;
mfPeerContext* mfp;
SURFACE_BITS_COMMAND* cmd;
update = client->update;
mfp = (mfPeerContext*) client->context;
cmd = &update->surface_bits_command;
s = mfp->s;
stream_clear(s);
stream_set_pos(s, 0);
rect.x = 0;
rect.y = 0;
rect.width = frameSize.width;
rect.height = frameSize.height;
rfx_compose_message(mfp->rfx_context, s, &rect, 1,
(BYTE*) pxdata, frameSize.width, frameSize.height, frameSize.width * 4);
UINT32 x = 0;
UINT32 y = 0;
cmd->destLeft = x;
cmd->destTop = y;
cmd->destRight = x + frameSize.width;
cmd->destBottom = y + frameSize.height;
cmd->bpp = 32;
cmd->codecID = 3;
cmd->width = frameSize.width;
cmd->height = frameSize.height;
cmd->bitmapDataLength = stream_get_length(s);
cmd->bitmapData = stream_get_head(s);
//send
printf("send\n");
update->SurfaceBits(update->context, cmd);
//clean up
CGColorSpaceRelease(rgbColorSpace);
CGImageRelease(image);
CGContextRelease(context);
CVPixelBufferUnlockBaseAddress(pxbuffer, 0);
CVPixelBufferRelease(pxbuffer);
}
void mf_peer_context_new(freerdp_peer* client, mfPeerContext* context)
@ -153,10 +318,10 @@ void mf_peer_context_new(freerdp_peer* client, mfPeerContext* context)
context->rfx_context->mode = RLGR3;
context->rfx_context->width = client->settings->DesktopWidth;
context->rfx_context->height = client->settings->DesktopHeight;
rfx_context_set_pixel_format(context->rfx_context, RDP_PIXEL_FORMAT_R8G8B8);
rfx_context_set_pixel_format(context->rfx_context, RDP_PIXEL_FORMAT_R8G8B8A8);
context->nsc_context = nsc_context_new();
nsc_context_set_pixel_format(context->nsc_context, RDP_PIXEL_FORMAT_R8G8B8);
nsc_context_set_pixel_format(context->nsc_context, RDP_PIXEL_FORMAT_R8G8B8A8);
context->s = stream_new(0xFFFF);
@ -220,6 +385,7 @@ static void mf_peer_init(freerdp_peer* client)
BOOL mf_peer_post_connect(freerdp_peer* client)
{
//mfPeerContext* context = (mfPeerContext*) client->context;
rdpSettings* settings = client->settings;
printf("Client %s is activated\n", client->hostname);
@ -232,10 +398,28 @@ BOOL mf_peer_post_connect(freerdp_peer* client)
/* A real server may perform OS login here if NLA is not executed previously. */
}
printf("\n");
UINT32 servscreen_width = 2880;
UINT32 servscreen_height = 1800;
UINT32 bitsPerPixel = 32;
if ((settings->DesktopWidth != servscreen_width) || (settings->DesktopHeight != servscreen_height))
{
printf("Client requested resolution %dx%d, but will resize to %dx%d\n",
settings->DesktopWidth, settings->DesktopHeight, servscreen_width, servscreen_height);
}
settings->DesktopWidth = servscreen_width;
settings->DesktopHeight = servscreen_height;
settings->ColorDepth = bitsPerPixel;
client->update->DesktopResize(client->update->context);
printf("Client requested desktop: %dx%dx%d\n",
/*printf("Client requested desktop: %dx%dx%d\n",
client->settings->DesktopWidth, client->settings->DesktopHeight, client->settings->ColorDepth);
*/
#ifdef WITH_SERVER_CHANNELS
/* Iterate all channel names requested by the client and activate those supported by the server */
int i;

View File

@ -45,4 +45,6 @@ struct mf_peer_context
};
typedef struct mf_peer_context mfPeerContext;
void mf_peer_rfx_update(freerdp_peer* client);
#endif /* MFREERDP_SERVER_H */