wfreerdp-server: fix encoding accuracy

This commit is contained in:
Marc-André Moreau
2012-09-02 19:54:17 -04:00
parent 7a0a8c3eb2
commit c1be07aa3d
5 changed files with 102 additions and 264 deletions

View File

@@ -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);
}

View File

@@ -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);

View File

@@ -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);
}
}

View File

@@ -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);
}

View File

@@ -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;