mirror of
https://github.com/morgan9e/FreeRDP
synced 2026-04-14 08:24:16 +09:00
wfreerdp-server: fix encoding accuracy
This commit is contained in:
@@ -109,20 +109,6 @@ wfInfo* wf_info_init()
|
||||
{
|
||||
_tprintf(_T("CreateMutex error: %d\n"), GetLastError());
|
||||
}
|
||||
|
||||
wfi->encodeMutex = CreateMutex(NULL, FALSE, NULL);
|
||||
|
||||
if (wfi->encodeMutex == NULL)
|
||||
{
|
||||
_tprintf(_T("CreateMutex error: %d\n"), GetLastError());
|
||||
}
|
||||
|
||||
wfi->can_send_mutex = CreateMutex(NULL, FALSE, NULL);
|
||||
|
||||
if (wfi->can_send_mutex == NULL)
|
||||
{
|
||||
_tprintf(_T("CreateMutex error: %d\n"), GetLastError());
|
||||
}
|
||||
}
|
||||
|
||||
return wfi;
|
||||
@@ -138,53 +124,31 @@ wfInfo* wf_info_get_instance()
|
||||
|
||||
void wf_info_mirror_init(wfInfo* wfi, wfPeerContext* context)
|
||||
{
|
||||
DWORD dRes;
|
||||
|
||||
dRes = WaitForSingleObject(wfi->mutex, INFINITE);
|
||||
|
||||
switch (dRes)
|
||||
if (wf_info_lock(wfi) > 0)
|
||||
{
|
||||
case WAIT_ABANDONED:
|
||||
case WAIT_OBJECT_0:
|
||||
if (wfi->subscribers < 1)
|
||||
{
|
||||
context->info = wfi;
|
||||
wf_check_disp_devices(wfi);
|
||||
wf_disp_device_set_attach_mode(wfi, 1);
|
||||
wf_update_mirror_drv(wfi, 0);
|
||||
wf_map_mirror_mem(wfi);
|
||||
|
||||
if (wfi->subscribers < 1)
|
||||
{
|
||||
/* only the first peer needs to call this. */
|
||||
wfi->rfx_context = rfx_context_new();
|
||||
wfi->rfx_context->mode = RLGR3;
|
||||
wfi->rfx_context->width = wfi->width;
|
||||
wfi->rfx_context->height = wfi->height;
|
||||
|
||||
context->info = wfi;
|
||||
wf_check_disp_devices(context->info);
|
||||
wf_disp_device_set_attach_mode(context->info, 1);
|
||||
wf_update_mirror_drv(context->info, 0);
|
||||
wf_map_mirror_mem(context->info);
|
||||
rfx_context_set_pixel_format(wfi->rfx_context, RDP_PIXEL_FORMAT_B8G8R8A8);
|
||||
wfi->s = stream_new(65536);
|
||||
}
|
||||
|
||||
context->rfx_context = rfx_context_new();
|
||||
context->rfx_context->mode = RLGR3;
|
||||
context->rfx_context->width = context->info->width;
|
||||
context->rfx_context->height = context->info->height;
|
||||
wfi->subscribers++;
|
||||
|
||||
rfx_context_set_pixel_format(context->rfx_context, RDP_PIXEL_FORMAT_B8G8R8A8);
|
||||
context->s = stream_new(65536);
|
||||
|
||||
context->info->primary_buffer = (BYTE*) malloc((context->info->width) * (context->info->height) * 4);
|
||||
|
||||
ReleaseMutex(wfi->encodeMutex);
|
||||
}
|
||||
++wfi->subscribers;
|
||||
|
||||
if (!ReleaseMutex(wfi->mutex))
|
||||
{
|
||||
_tprintf(_T("Error releasing mutex\n"));
|
||||
}
|
||||
|
||||
break;
|
||||
|
||||
default:
|
||||
_tprintf(_T("Error waiting for mutex: %d\n"), dRes);
|
||||
break;
|
||||
wf_info_unlock(wfi);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* TODO: i think i can replace all the context->info here with info
|
||||
* in fact it may not even care about subscribers
|
||||
@@ -192,46 +156,26 @@ void wf_info_mirror_init(wfInfo* wfi, wfPeerContext* context)
|
||||
|
||||
void wf_info_subscriber_release(wfInfo* wfi, wfPeerContext* context)
|
||||
{
|
||||
DWORD dRes;
|
||||
|
||||
WaitForSingleObject(wfi->mutex, INFINITE);
|
||||
|
||||
if (context && (wfi->subscribers == 1))
|
||||
if (wf_info_lock(wfi) > 0)
|
||||
{
|
||||
dRes = WaitForSingleObject(wfi->encodeMutex, INFINITE);
|
||||
|
||||
switch (dRes)
|
||||
if (context && (wfi->subscribers == 1))
|
||||
{
|
||||
/* The thread got ownership of the mutex */
|
||||
|
||||
case WAIT_OBJECT_0:
|
||||
--wfi->subscribers;
|
||||
/* only the last peer needs to call this */
|
||||
wf_mirror_cleanup(context->info);
|
||||
wf_disp_device_set_attach_mode(context->info, FALSE);
|
||||
wf_update_mirror_drv(context->info, 1);
|
||||
wfi->subscribers--;
|
||||
/* only the last peer needs to call this */
|
||||
wf_mirror_cleanup(context->info);
|
||||
wf_disp_device_set_attach_mode(context->info, FALSE);
|
||||
wf_update_mirror_drv(context->info, 1);
|
||||
|
||||
stream_free(context->s);
|
||||
rfx_context_free(context->rfx_context);
|
||||
|
||||
free(context->info->primary_buffer);
|
||||
break;
|
||||
|
||||
/**
|
||||
* The thread got ownership of an abandoned mutex
|
||||
* The database is in an indeterminate state
|
||||
*/
|
||||
default:
|
||||
printf("wf_info_subscriber_release: Something else happened!!! dRes = %d\n", dRes);
|
||||
break;
|
||||
stream_free(wfi->s);
|
||||
rfx_context_free(wfi->rfx_context);
|
||||
}
|
||||
else
|
||||
{
|
||||
wfi->subscribers--;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
--wfi->subscribers;
|
||||
}
|
||||
|
||||
ReleaseMutex(wfi->mutex);
|
||||
wf_info_unlock(wfi);
|
||||
}
|
||||
|
||||
/**
|
||||
* Note: if we released the last subscriber,
|
||||
@@ -255,11 +199,6 @@ BOOL wf_info_have_updates(wfInfo* wfi)
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
void wf_info_updated(wfInfo* wfi)
|
||||
{
|
||||
wfi->lastUpdate = wfi->nextUpdate;
|
||||
}
|
||||
|
||||
void wf_info_update_changes(wfInfo* wfi)
|
||||
{
|
||||
GETCHANGESBUF* buf;
|
||||
@@ -275,53 +214,31 @@ void wf_info_find_invalid_region(wfInfo* wfi)
|
||||
|
||||
buf = (GETCHANGESBUF*) wfi->changeBuffer;
|
||||
|
||||
if (wfi->enc_data == FALSE)
|
||||
{
|
||||
wfi->invalid_x1 = wfi->width - 1;
|
||||
wfi->invalid_x2 = 0;
|
||||
wfi->invalid_y1 = wfi->height - 1;
|
||||
wfi->invalid_y2 = 0;
|
||||
}
|
||||
|
||||
for (i = wfi->lastUpdate; i != wfi->nextUpdate; i = (i + 1) % MAXCHANGES_BUF)
|
||||
{
|
||||
wfi->invalid_x1 = min(wfi->invalid_x1, buf->buffer->pointrect[i].rect.left);
|
||||
wfi->invalid_x2 = max(wfi->invalid_x2, buf->buffer->pointrect[i].rect.right);
|
||||
wfi->invalid_y1 = min(wfi->invalid_y1, buf->buffer->pointrect[i].rect.top);
|
||||
wfi->invalid_y2 = max(wfi->invalid_y2, buf->buffer->pointrect[i].rect.bottom);
|
||||
UnionRect(&wfi->invalid, &wfi->invalid, &buf->buffer->pointrect[i].rect);
|
||||
}
|
||||
|
||||
if (wfi->invalid_x1 < 0)
|
||||
wfi->invalid_x1 = 0;
|
||||
if (wfi->invalid.left < 0)
|
||||
wfi->invalid.left = 0;
|
||||
|
||||
if (wfi->invalid_y1 < 0)
|
||||
wfi->invalid_y1 = 0;
|
||||
if (wfi->invalid.top < 0)
|
||||
wfi->invalid.top = 0;
|
||||
|
||||
if (wfi->invalid_x2 >= wfi->width)
|
||||
wfi->invalid_x2 = wfi->width - 1;
|
||||
if (wfi->invalid.right >= wfi->width)
|
||||
wfi->invalid.right = wfi->width - 1;
|
||||
|
||||
if (wfi->invalid_y2 >= wfi->height)
|
||||
wfi->invalid_y2 = wfi->height - 1;
|
||||
if (wfi->invalid.bottom >= wfi->height)
|
||||
wfi->invalid.bottom = wfi->height - 1;
|
||||
}
|
||||
|
||||
void wf_info_clear_invalid_region(wfInfo* wfi)
|
||||
{
|
||||
WaitForSingleObject(wfi->mutex, INFINITE);
|
||||
|
||||
wfi->lastUpdate = wfi->nextUpdate;
|
||||
|
||||
wfi->invalid_x1 = wfi->width - 1;
|
||||
wfi->invalid_x2 = 0;
|
||||
wfi->invalid_y1 = wfi->height - 1;
|
||||
wfi->invalid_y2 = 0;
|
||||
|
||||
ReleaseMutex(wfi->mutex);
|
||||
SetRectEmpty(&wfi->invalid);
|
||||
}
|
||||
|
||||
BOOL wf_info_have_invalid_region(wfInfo* wfi)
|
||||
{
|
||||
if ((wfi->invalid_x1 >= wfi->invalid_x2) || (wfi->invalid_y1 >= wfi->invalid_y2))
|
||||
return FALSE;
|
||||
|
||||
return TRUE;
|
||||
return IsRectEmpty(&wfi->invalid);
|
||||
}
|
||||
|
||||
@@ -20,11 +20,14 @@
|
||||
#ifndef WF_INFO_H
|
||||
#define WF_INFO_H
|
||||
|
||||
#include <freerdp/codec/rfx.h>
|
||||
|
||||
struct wf_peer_context;
|
||||
typedef struct wf_peer_context wfPeerContext;
|
||||
|
||||
struct wf_info
|
||||
{
|
||||
STREAM* s;
|
||||
HDC driverDC;
|
||||
BOOL activated;
|
||||
void* changeBuffer;
|
||||
@@ -36,22 +39,12 @@ struct wf_info
|
||||
int width;
|
||||
int bitsPerPix;
|
||||
|
||||
RECT invalid;
|
||||
HANDLE mutex;
|
||||
HANDLE encodeMutex;
|
||||
HANDLE can_send_mutex;
|
||||
|
||||
BOOL updatePending;
|
||||
RFX_CONTEXT* rfx_context;
|
||||
unsigned long lastUpdate;
|
||||
unsigned long nextUpdate;
|
||||
|
||||
long invalid_x1;
|
||||
long invalid_y1;
|
||||
|
||||
long invalid_x2;
|
||||
long invalid_y2;
|
||||
|
||||
BOOL enc_data;
|
||||
|
||||
BYTE* primary_buffer;
|
||||
};
|
||||
typedef struct wf_info wfInfo;
|
||||
|
||||
@@ -65,7 +58,6 @@ void wf_info_subscriber_release(wfInfo* wfi, wfPeerContext* context);
|
||||
|
||||
BOOL wf_info_has_subscribers(wfInfo* wfi);
|
||||
BOOL wf_info_have_updates(wfInfo* wfi);
|
||||
void wf_info_updated(wfInfo* wfi);
|
||||
void wf_info_update_changes(wfInfo* wfi);
|
||||
void wf_info_find_invalid_region(wfInfo* wfi);
|
||||
void wf_info_clear_invalid_region(wfInfo* wfi);
|
||||
|
||||
@@ -67,18 +67,21 @@ static DWORD WINAPI wf_peer_mirror_monitor(LPVOID lpParam)
|
||||
{
|
||||
beg = GetTickCount();
|
||||
|
||||
wf_info_lock(wfi);
|
||||
|
||||
if (wf_info_has_subscribers(wfi))
|
||||
if (wf_info_lock(wfi) > 0)
|
||||
{
|
||||
wf_info_update_changes(wfi);
|
||||
if (wf_info_has_subscribers(wfi))
|
||||
{
|
||||
wf_info_update_changes(wfi);
|
||||
|
||||
if (wf_info_have_updates(wfi))
|
||||
wf_rfx_encode(client);
|
||||
if (wf_info_have_updates(wfi))
|
||||
{
|
||||
wf_rfx_encode(client);
|
||||
}
|
||||
}
|
||||
|
||||
wf_info_unlock(wfi);
|
||||
}
|
||||
|
||||
wf_info_unlock(wfi);
|
||||
|
||||
end = GetTickCount();
|
||||
diff = end - beg;
|
||||
|
||||
@@ -97,7 +100,6 @@ static DWORD WINAPI wf_peer_mirror_monitor(LPVOID lpParam)
|
||||
|
||||
void wf_rfx_encode(freerdp_peer* client)
|
||||
{
|
||||
int dRes;
|
||||
STREAM* s;
|
||||
wfInfo* wfi;
|
||||
long offset;
|
||||
@@ -108,101 +110,51 @@ void wf_rfx_encode(freerdp_peer* client)
|
||||
GETCHANGESBUF* buf;
|
||||
SURFACE_BITS_COMMAND* cmd;
|
||||
|
||||
#ifdef WITH_DOUBLE_BUFFERING
|
||||
uint16 i;
|
||||
int scanline;
|
||||
BYTE* srcp;
|
||||
BYTE* dstp;
|
||||
#endif
|
||||
wfp = (wfPeerContext*) client->context;
|
||||
wfi = wfp->info;
|
||||
|
||||
if (client->activated == FALSE)
|
||||
return;
|
||||
|
||||
wfp = (wfPeerContext*) client->context;
|
||||
wfi = wfp->info;
|
||||
if (wfp->activated == FALSE)
|
||||
return;
|
||||
|
||||
dRes = WaitForSingleObject(wfi->encodeMutex, INFINITE);
|
||||
wf_info_find_invalid_region(wfi);
|
||||
|
||||
switch (dRes)
|
||||
{
|
||||
case WAIT_ABANDONED:
|
||||
case WAIT_OBJECT_0:
|
||||
update = client->update;
|
||||
cmd = &update->surface_bits_command;
|
||||
buf = (GETCHANGESBUF*) wfi->changeBuffer;
|
||||
|
||||
wf_info_find_invalid_region(wfi);
|
||||
width = (wfi->invalid.right - wfi->invalid.left) + 1;
|
||||
height = (wfi->invalid.bottom - wfi->invalid.top) + 1;
|
||||
|
||||
if ((wfp->activated == false) ||
|
||||
(wf_info_has_subscribers(wfi) == false) ||
|
||||
!wf_info_have_invalid_region(wfi) ||
|
||||
(wfi->enc_data == true) )
|
||||
{
|
||||
ReleaseMutex(wfi->encodeMutex);
|
||||
break;
|
||||
}
|
||||
stream_clear(wfi->s);
|
||||
stream_set_pos(wfi->s, 0);
|
||||
s = wfi->s;
|
||||
|
||||
update = client->update;
|
||||
cmd = &update->surface_bits_command;
|
||||
buf = (GETCHANGESBUF*) wfi->changeBuffer;
|
||||
rect.x = 0;
|
||||
rect.y = 0;
|
||||
rect.width = (uint16) width;
|
||||
rect.height = (uint16) height;
|
||||
|
||||
width = (wfi->invalid_x2 - wfi->invalid_x1) + 1;
|
||||
height = (wfi->invalid_y2 - wfi->invalid_y1) + 1;
|
||||
offset = (4 * wfi->invalid.left) + (wfi->invalid.top * wfi->width * 4);
|
||||
|
||||
stream_clear(wfp->s);
|
||||
stream_set_pos(wfp->s, 0);
|
||||
s = wfp->s;
|
||||
|
||||
rect.x = 0;
|
||||
rect.y = 0;
|
||||
rect.width = (uint16) width;
|
||||
rect.height = (uint16) height;
|
||||
|
||||
#ifndef WITH_DOUBLE_BUFFERING
|
||||
offset = (4 * wfi->invalid_x1) + (wfi->invalid_y1 * wfi->width * 4);
|
||||
rfx_compose_message(wfi->rfx_context, s, &rect, 1,
|
||||
((uint8*) (buf->Userbuffer)) + offset, width, height, wfi->width * 4);
|
||||
|
||||
|
||||
rfx_compose_message(wfp->rfx_context, s, &rect, 1,
|
||||
((uint8*) (buf->Userbuffer)) + offset, width, height, wfi->width * 4);
|
||||
#else
|
||||
scanline = (wfi->width * 4);
|
||||
offset = (wfi->invalid_y1 * scanline) + (wfi->invalid_x1 * 4);
|
||||
srcp = (BYTE*) buf->Userbuffer + offset;
|
||||
dstp = (BYTE*) wfi->primary_buffer + offset;
|
||||
cmd->destLeft = wfi->invalid.left;
|
||||
cmd->destTop = wfi->invalid.top;
|
||||
cmd->destRight = wfi->invalid.left + width;
|
||||
cmd->destBottom = wfi->invalid.top + height;
|
||||
|
||||
for (i = 0; i < height; i++)
|
||||
{
|
||||
memcpy(dstp, srcp, width * 4);
|
||||
dstp += scanline;
|
||||
srcp += scanline;
|
||||
}
|
||||
|
||||
rfx_compose_message(wfp->rfx_context, s, &rect, 1,
|
||||
wfi->primary_buffer + offset, width, height, wfi->width * 4);
|
||||
#endif
|
||||
|
||||
cmd->destLeft = wfi->invalid_x1;
|
||||
cmd->destTop = wfi->invalid_y1;
|
||||
cmd->destRight = wfi->invalid_x1 + width;
|
||||
cmd->destBottom = wfi->invalid_y1 + height;
|
||||
|
||||
cmd->bpp = 32;
|
||||
cmd->codecID = client->settings->rfx_codec_id;
|
||||
cmd->width = width;
|
||||
cmd->height = height;
|
||||
cmd->bitmapDataLength = stream_get_length(s);
|
||||
cmd->bitmapData = stream_get_head(s);
|
||||
|
||||
wfi->enc_data = true;
|
||||
ReleaseMutex(wfi->encodeMutex);
|
||||
break;
|
||||
|
||||
case WAIT_TIMEOUT:
|
||||
|
||||
ReleaseMutex(wfi->encodeMutex);
|
||||
break;
|
||||
|
||||
default:
|
||||
break;
|
||||
}
|
||||
cmd->bpp = 32;
|
||||
cmd->codecID = client->settings->rfx_codec_id;
|
||||
cmd->width = width;
|
||||
cmd->height = height;
|
||||
cmd->bitmapDataLength = stream_get_length(s);
|
||||
cmd->bitmapData = stream_get_head(s);
|
||||
|
||||
wfi->updatePending = TRUE;
|
||||
}
|
||||
|
||||
void wf_peer_init(freerdp_peer* client)
|
||||
@@ -293,43 +245,22 @@ void wf_peer_synchronize_event(rdpInput* input, uint32 flags)
|
||||
|
||||
void wf_peer_send_changes(freerdp_peer* client)
|
||||
{
|
||||
int dRes;
|
||||
wfInfo* wfi;
|
||||
wfPeerContext* context = (wfPeerContext*) client->context;
|
||||
|
||||
wfi = context->info;
|
||||
|
||||
/* are we currently encoding? */
|
||||
dRes = WaitForSingleObject(wfi->encodeMutex, 0);
|
||||
|
||||
switch (dRes)
|
||||
if (wf_info_lock(wfi) > 0)
|
||||
{
|
||||
case WAIT_ABANDONED:
|
||||
case WAIT_OBJECT_0:
|
||||
if (wfi->updatePending)
|
||||
{
|
||||
wfi->lastUpdate = wfi->nextUpdate;
|
||||
|
||||
if (wf_info_try_lock(wfi, 100) != -1)
|
||||
{
|
||||
if ((!wf_info_have_updates(wfi) || !wf_info_have_invalid_region(wfi) || (wfi->enc_data == FALSE)))
|
||||
{
|
||||
wf_info_unlock(wfi);
|
||||
ReleaseMutex(wfi->encodeMutex);
|
||||
break;
|
||||
}
|
||||
client->update->SurfaceBits(client->update->context, &client->update->surface_bits_command);
|
||||
|
||||
wf_info_updated(wfi);
|
||||
wfi->updatePending = FALSE;
|
||||
}
|
||||
|
||||
client->update->SurfaceBits(client->update->context, &client->update->surface_bits_command);
|
||||
|
||||
wfi->enc_data = FALSE;
|
||||
wf_info_unlock(wfi);
|
||||
ReleaseMutex(wfi->encodeMutex);
|
||||
}
|
||||
break;
|
||||
|
||||
case WAIT_TIMEOUT:
|
||||
break;
|
||||
|
||||
default:
|
||||
break;
|
||||
wf_info_unlock(wfi);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -92,7 +92,7 @@ static DWORD WINAPI wf_peer_main_loop(LPVOID lpParam)
|
||||
}
|
||||
|
||||
#ifndef WITH_WIN8
|
||||
if(client->activated)
|
||||
if (client->activated)
|
||||
wf_peer_send_changes(client);
|
||||
#endif
|
||||
}
|
||||
@@ -136,6 +136,7 @@ static void wf_server_main_loop(freerdp_listener* instance)
|
||||
printf("Failed to check FreeRDP file descriptor\n");
|
||||
break;
|
||||
}
|
||||
|
||||
Sleep(20);
|
||||
}
|
||||
|
||||
|
||||
@@ -21,20 +21,17 @@
|
||||
#define WFREERDP_H
|
||||
|
||||
//#define WITH_WIN8 1
|
||||
//#define WITH_DOUBLE_BUFFERING 1
|
||||
|
||||
#include <freerdp/freerdp.h>
|
||||
#include <freerdp/codec/rfx.h>
|
||||
|
||||
#include "wf_info.h"
|
||||
|
||||
struct wf_peer_context
|
||||
{
|
||||
rdpContext _p;
|
||||
|
||||
STREAM* s;
|
||||
wfInfo* info;
|
||||
boolean activated;
|
||||
RFX_CONTEXT* rfx_context;
|
||||
};
|
||||
typedef struct wf_peer_context wfPeerContext;
|
||||
|
||||
|
||||
Reference in New Issue
Block a user