mfreerdp-server: got rfx working at 1fps
This commit is contained in:
parent
05cd1dc600
commit
b33b0380b0
@ -18,6 +18,7 @@
|
|||||||
set(MODULE_NAME "mfreerdp-server")
|
set(MODULE_NAME "mfreerdp-server")
|
||||||
set(MODULE_PREFIX "FREERDP_SERVER_MAC")
|
set(MODULE_PREFIX "FREERDP_SERVER_MAC")
|
||||||
|
|
||||||
|
FIND_LIBRARY(CORE_VIDEO CoreVideo)
|
||||||
FIND_LIBRARY(CORE_GRAPHICS CoreGraphics)
|
FIND_LIBRARY(CORE_GRAPHICS CoreGraphics)
|
||||||
FIND_LIBRARY(APP_SERVICES ApplicationServices)
|
FIND_LIBRARY(APP_SERVICES ApplicationServices)
|
||||||
|
|
||||||
@ -44,6 +45,7 @@ add_executable(${MODULE_NAME} ${${MODULE_PREFIX}_SRCS})
|
|||||||
|
|
||||||
set(${MODULE_PREFIX}_LIBS ${${MODULE_PREFIX}_LIBS}
|
set(${MODULE_PREFIX}_LIBS ${${MODULE_PREFIX}_LIBS}
|
||||||
freerdp-server
|
freerdp-server
|
||||||
|
${CORE_VIDEO}
|
||||||
${CORE_GRAPHICS}
|
${CORE_GRAPHICS}
|
||||||
${APP_SERVICES})
|
${APP_SERVICES})
|
||||||
|
|
||||||
|
@ -55,6 +55,11 @@
|
|||||||
#include <mach/mach.h>
|
#include <mach/mach.h>
|
||||||
#include <dispatch/dispatch.h>
|
#include <dispatch/dispatch.h>
|
||||||
|
|
||||||
|
#include "OpenGL/OpenGL.h"
|
||||||
|
#include "OpenGL/gl.h"
|
||||||
|
|
||||||
|
#include "CoreVideo/CoreVideo.h"
|
||||||
|
|
||||||
//refactor these
|
//refactor these
|
||||||
int info_last_sec = 0;
|
int info_last_sec = 0;
|
||||||
int info_last_nsec = 0;
|
int info_last_nsec = 0;
|
||||||
@ -64,6 +69,62 @@ dispatch_queue_t info_queue;
|
|||||||
|
|
||||||
mfEventQueue* info_event_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)
|
BOOL mf_peer_get_fds(freerdp_peer* client, void** rfds, int* rcount)
|
||||||
{
|
{
|
||||||
if (info_event_queue->pipe_fd[0] == -1)
|
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);
|
event = mf_event_pop(info_event_queue);
|
||||||
|
|
||||||
printf("Tick\n");
|
printf("Tick\n");
|
||||||
|
|
||||||
|
mf_peer_rfx_update(client);
|
||||||
|
|
||||||
/*invalid_region = xfp->hdc->hwnd->invalid;
|
/*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)
|
void mf_peer_rfx_update(freerdp_peer* client)
|
||||||
{
|
{
|
||||||
|
|
||||||
//limit rate
|
//check
|
||||||
/*
|
/*if (servscreen_height * servscreen_width == 0)
|
||||||
clock_serv_t cclock;
|
return;
|
||||||
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);
|
|
||||||
|
|
||||||
if ( (mts.tv_sec - info_last_sec > 0) && (mts.tv_nsec - info_last_nsec > 500000000) ) {
|
if(cnt++ < 10)
|
||||||
printf("rfx_update\n");
|
return;
|
||||||
|
|
||||||
info_last_nsec = mts.tv_nsec;
|
|
||||||
info_last_sec = mts.tv_sec;
|
|
||||||
}
|
|
||||||
*/
|
*/
|
||||||
|
|
||||||
//capture entire screen
|
//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
|
//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
|
//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)
|
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->mode = RLGR3;
|
||||||
context->rfx_context->width = client->settings->DesktopWidth;
|
context->rfx_context->width = client->settings->DesktopWidth;
|
||||||
context->rfx_context->height = client->settings->DesktopHeight;
|
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();
|
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);
|
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)
|
BOOL mf_peer_post_connect(freerdp_peer* client)
|
||||||
{
|
{
|
||||||
//mfPeerContext* context = (mfPeerContext*) client->context;
|
//mfPeerContext* context = (mfPeerContext*) client->context;
|
||||||
|
rdpSettings* settings = client->settings;
|
||||||
|
|
||||||
printf("Client %s is activated\n", client->hostname);
|
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. */
|
/* A real server may perform OS login here if NLA is not executed previously. */
|
||||||
}
|
}
|
||||||
printf("\n");
|
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);
|
client->settings->DesktopWidth, client->settings->DesktopHeight, client->settings->ColorDepth);
|
||||||
|
*/
|
||||||
#ifdef WITH_SERVER_CHANNELS
|
#ifdef WITH_SERVER_CHANNELS
|
||||||
/* Iterate all channel names requested by the client and activate those supported by the server */
|
/* Iterate all channel names requested by the client and activate those supported by the server */
|
||||||
int i;
|
int i;
|
||||||
|
@ -45,4 +45,6 @@ struct mf_peer_context
|
|||||||
};
|
};
|
||||||
typedef struct mf_peer_context mfPeerContext;
|
typedef struct mf_peer_context mfPeerContext;
|
||||||
|
|
||||||
|
void mf_peer_rfx_update(freerdp_peer* client);
|
||||||
|
|
||||||
#endif /* MFREERDP_SERVER_H */
|
#endif /* MFREERDP_SERVER_H */
|
||||||
|
Loading…
Reference in New Issue
Block a user