mfreerdp-server: refactored screen capture, fixed corruption issue
This commit is contained in:
parent
3d0d88720d
commit
777bc6cd80
@ -277,6 +277,12 @@ BOOL mf_info_have_invalid_region(mfInfo* mfi)
|
||||
|
||||
void mf_info_getScreenData(mfInfo* mfi, long* width, long* height, BYTE** pBits, int* pitch)
|
||||
{
|
||||
*width = mfi->invalid.width / 2;
|
||||
*height = mfi->invalid.height / 2;
|
||||
*pitch = 2880 * 4;
|
||||
|
||||
mf_mlion_get_pixelData(mfi->invalid.x / 2, mfi->invalid.y / 2, *width, *height, pBits);
|
||||
|
||||
/*
|
||||
*width = (mfi->invalid.right - mfi->invalid.left);
|
||||
*height = (mfi->invalid.bottom - mfi->invalid.top);
|
||||
|
@ -19,6 +19,7 @@
|
||||
|
||||
#include <dispatch/dispatch.h>
|
||||
#include <CoreGraphics/CoreGraphics.h>
|
||||
#include "CoreVideo/CoreVideo.h"
|
||||
|
||||
//#include <pthread.h>
|
||||
|
||||
@ -32,7 +33,12 @@ CGDisplayStreamUpdateRef lastUpdate = NULL;
|
||||
|
||||
//pthread_mutex_t mutex = PTHREAD_MUTEX_INITIALIZER;
|
||||
|
||||
CVPixelBufferRef pxbuffer = NULL;
|
||||
void *baseAddress = NULL;
|
||||
|
||||
CGContextRef bitmapcontext = NULL;
|
||||
|
||||
CGImageRef image = NULL;
|
||||
|
||||
void (^streamHandler)(CGDisplayStreamFrameStatus, uint64_t, IOSurfaceRef, CGDisplayStreamUpdateRef) = ^(CGDisplayStreamFrameStatus status, uint64_t displayTime, IOSurfaceRef frameSurface, CGDisplayStreamUpdateRef updateRef)
|
||||
{
|
||||
@ -142,6 +148,58 @@ int mf_mlion_screen_updates_init()
|
||||
screen_update_q,
|
||||
streamHandler);
|
||||
|
||||
|
||||
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;
|
||||
}
|
||||
|
||||
CVReturn status = CVPixelBufferCreate(kCFAllocatorDefault, pixelWidth,
|
||||
pixelHeight, kCVPixelFormatType_32ARGB, opts,
|
||||
&pxbuffer);
|
||||
|
||||
if (status != kCVReturnSuccess)
|
||||
{
|
||||
printf("Failed to create pixel buffer! \n");
|
||||
//return 1;
|
||||
}
|
||||
|
||||
CFRelease(opts);
|
||||
|
||||
CVPixelBufferLockBaseAddress(pxbuffer, 0);
|
||||
baseAddress = CVPixelBufferGetBaseAddress(pxbuffer);
|
||||
|
||||
CGColorSpaceRef rgbColorSpace = CGColorSpaceCreateDeviceRGB();
|
||||
|
||||
bitmapcontext = CGBitmapContextCreate(baseAddress,
|
||||
pixelWidth,
|
||||
pixelHeight, 8, 4*pixelWidth, rgbColorSpace,
|
||||
kCGImageAlphaNoneSkipLast);
|
||||
|
||||
if (bitmapcontext == NULL) {
|
||||
printf("context = null!!!\n\n\n");
|
||||
}
|
||||
CGColorSpaceRelease(rgbColorSpace);
|
||||
|
||||
|
||||
return 0;
|
||||
|
||||
}
|
||||
@ -211,4 +269,24 @@ int mf_mlion_clear_dirty_region()
|
||||
dispatch_semaphore_signal(region_sem);
|
||||
*/
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
int mf_mlion_get_pixelData(long x, long y, long width, long height, BYTE** pxData)
|
||||
{
|
||||
if (image != NULL) {
|
||||
CGImageRelease(image);
|
||||
}
|
||||
image = CGDisplayCreateImageForRect(
|
||||
kCGDirectMainDisplay,
|
||||
CGRectMake(x, y, width, height) );
|
||||
|
||||
CGContextDrawImage(
|
||||
bitmapcontext,
|
||||
CGRectMake(0, 1800 - height, width, height),
|
||||
image);
|
||||
|
||||
*pxData = baseAddress;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
@ -31,4 +31,6 @@ int mf_mlion_stop_getting_screen_updates();
|
||||
int mf_mlion_get_dirty_region(RFX_RECT* invalid);
|
||||
int mf_mlion_clear_dirty_region();
|
||||
|
||||
int mf_mlion_get_pixelData(long x, long y, long width, long height, BYTE **pxData);
|
||||
|
||||
#endif
|
@ -116,7 +116,6 @@ BOOL mf_peer_check_fds(freerdp_peer* client)
|
||||
|
||||
void mf_peer_rfx_update(freerdp_peer* client)
|
||||
{
|
||||
|
||||
//check
|
||||
mfInfo* mfi = mf_info_get_instance();
|
||||
|
||||
@ -125,15 +124,13 @@ void mf_peer_rfx_update(freerdp_peer* client)
|
||||
if (mf_info_have_invalid_region(mfi) == false) {
|
||||
return;
|
||||
}
|
||||
|
||||
/*
|
||||
printf("\tinvalid -> (%d,%d), (%d,%d)\n",
|
||||
mfi->invalid.x,
|
||||
mfi->invalid.y,
|
||||
mfi->invalid.x + mfi->invalid.width,
|
||||
mfi->invalid.y + mfi->invalid.height);
|
||||
|
||||
//capture entire screen
|
||||
|
||||
|
||||
int bytewidth;
|
||||
|
||||
CGRect invRect;
|
||||
@ -147,6 +144,10 @@ void mf_peer_rfx_update(freerdp_peer* client)
|
||||
CGImageRef image = CGDisplayCreateImageForRect(kCGDirectMainDisplay, invRect);
|
||||
//CGSize frameSize = CGSizeMake(CGImageGetWidth(image), CGImageGetHeight(image)); // Get screenshot bounds
|
||||
|
||||
if (image == NULL) {
|
||||
printf("image = null!!\n\n\n");
|
||||
}
|
||||
|
||||
CGSize frameSize;
|
||||
frameSize.width = 2880 / 2;
|
||||
frameSize.height = 1800/ 2;
|
||||
@ -175,10 +176,7 @@ void mf_peer_rfx_update(freerdp_peer* client)
|
||||
}
|
||||
|
||||
CVPixelBufferRef pxbuffer = NULL;
|
||||
/*CVReturn status = CVPixelBufferCreate(kCFAllocatorDefault, frameSize.width,
|
||||
frameSize.height, kCVPixelFormatType_32ARGB, opts,
|
||||
&pxbuffer);
|
||||
*/
|
||||
|
||||
CVReturn status = CVPixelBufferCreate(kCFAllocatorDefault, invRect.size.width,
|
||||
invRect.size.height, kCVPixelFormatType_32ARGB, opts,
|
||||
&pxbuffer);
|
||||
@ -195,15 +193,22 @@ void mf_peer_rfx_update(freerdp_peer* client)
|
||||
void *pxdata = CVPixelBufferGetBaseAddress(pxbuffer);
|
||||
|
||||
CGColorSpaceRef rgbColorSpace = CGColorSpaceCreateDeviceRGB();
|
||||
/*CGContextRef context = CGBitmapContextCreate(pxdata, frameSize.width,
|
||||
frameSize.height, 8, 4*frameSize.width, rgbColorSpace,
|
||||
kCGImageAlphaNoneSkipLast);
|
||||
*/
|
||||
|
||||
CGContextRef context = CGBitmapContextCreate(pxdata,
|
||||
invRect.size.width,
|
||||
invRect.size.height, 8, 4*frameSize.width, rgbColorSpace,
|
||||
kCGImageAlphaNoneSkipLast);
|
||||
|
||||
|
||||
if (context == NULL) {
|
||||
printf("context = null!!!\n\n\n");
|
||||
}
|
||||
|
||||
printf("context = [%p], image = [%p]\n%fx%f\n",
|
||||
context,
|
||||
image,
|
||||
invRect.size.width,
|
||||
invRect.size.height);
|
||||
|
||||
CGContextDrawImage(context,
|
||||
CGRectMake(0, 0, invRect.size.width, invRect.size.height),
|
||||
//CGRectMake(invRect.origin.x, frameSize.height - invRect.origin.y, invRect.size.width, invRect.size.height),
|
||||
@ -212,6 +217,14 @@ void mf_peer_rfx_update(freerdp_peer* client)
|
||||
|
||||
bytewidth = frameSize.width * 4; // Assume 4 bytes/pixel for now
|
||||
bytewidth = (bytewidth + 3) & ~3; // Align to 4 bytes
|
||||
*/
|
||||
|
||||
long width;
|
||||
long height;
|
||||
int pitch;
|
||||
BYTE* dataBits = NULL;
|
||||
|
||||
mf_info_getScreenData(mfi, &width, &height, &dataBits, &pitch);
|
||||
|
||||
//encode
|
||||
|
||||
@ -233,11 +246,11 @@ void mf_peer_rfx_update(freerdp_peer* client)
|
||||
|
||||
rect.x = 0;
|
||||
rect.y = 0;
|
||||
rect.width = mfi->invalid.width / 2;
|
||||
rect.height = mfi->invalid.height / 2;
|
||||
rect.width = width;
|
||||
rect.height = height;
|
||||
|
||||
rfx_compose_message(mfp->rfx_context, s, &rect, 1,
|
||||
(BYTE*) pxdata, rect.width, rect.height, frameSize.width * 4);
|
||||
(BYTE*) dataBits, rect.width, rect.height, pitch);
|
||||
|
||||
UINT32 x = mfi->invalid.x / 2;
|
||||
UINT32 y = mfi->invalid.y / 2;
|
||||
@ -264,13 +277,14 @@ void mf_peer_rfx_update(freerdp_peer* client)
|
||||
|
||||
mf_info_clear_invalid_region(mfi);
|
||||
// note: need to stop getting new dirty rects until here
|
||||
|
||||
/*
|
||||
CGColorSpaceRelease(rgbColorSpace);
|
||||
CGImageRelease(image);
|
||||
CGContextRelease(context);
|
||||
|
||||
CVPixelBufferUnlockBaseAddress(pxbuffer, 0);
|
||||
CVPixelBufferRelease(pxbuffer);
|
||||
*/
|
||||
}
|
||||
|
||||
/* Called when we have a new peer connecting */
|
||||
@ -342,7 +356,7 @@ void mf_peer_init(freerdp_peer* client)
|
||||
if(info_timer)
|
||||
{
|
||||
//printf("created timer\n");
|
||||
dispatch_source_set_timer(info_timer, DISPATCH_TIME_NOW, 1ull * NSEC_PER_SEC, 100ull * NSEC_PER_MSEC);
|
||||
dispatch_source_set_timer(info_timer, DISPATCH_TIME_NOW, 500ull * NSEC_PER_MSEC, 100ull * NSEC_PER_MSEC);
|
||||
dispatch_source_set_event_handler(info_timer, ^{
|
||||
printf("dispatch\n");
|
||||
mfEvent* event = mf_event_new(MF_EVENT_TYPE_FRAME_TICK);
|
||||
@ -371,8 +385,8 @@ BOOL mf_peer_post_connect(freerdp_peer* client)
|
||||
printf("\n");
|
||||
|
||||
|
||||
UINT32 servscreen_width = 2880;
|
||||
UINT32 servscreen_height = 1800;
|
||||
UINT32 servscreen_width = 2880 / 2;
|
||||
UINT32 servscreen_height = 1800 / 2;
|
||||
UINT32 bitsPerPixel = 32;
|
||||
|
||||
if ((settings->DesktopWidth != servscreen_width) || (settings->DesktopHeight != servscreen_height))
|
||||
|
Loading…
x
Reference in New Issue
Block a user