wfreerdp-server: fix race condition in encoder reset

This commit is contained in:
Marc-André Moreau
2012-09-16 23:09:36 -04:00
parent d315af5feb
commit 1a011fee45
4 changed files with 58 additions and 35 deletions

3
.gitignore vendored
View File

@@ -48,6 +48,9 @@ xcode
# Other
*~
*.dir
Release
Win32
default.log
*Amplifier XE*

View File

@@ -37,6 +37,7 @@ struct wf_info
STREAM* s;
int width;
int height;
int frame_idx;
int bitsPerPixel;
HDC driverDC;
int peerCount;
@@ -65,6 +66,7 @@ struct wf_peer_context
rdpContext _p;
wfInfo* info;
int frame_idx;
HANDLE updateEvent;
BOOL socketClose;
HANDLE socketEvent;

View File

@@ -260,14 +260,14 @@ DWORD WINAPI wf_peer_main_loop(LPVOID lpParam)
printf("Client %s disconnected.\n", client->local ? "(local)" : client->hostname);
wf_update_peer_deactivate(wfi, context);
if (WaitForSingleObject(context->updateEvent, 0) == 0)
{
ResetEvent(context->updateEvent);
ReleaseSemaphore(wfi->updateSemaphore, 1, NULL);
}
wf_update_peer_deactivate(wfi, context);
client->Disconnect(client);
freerdp_peer_context_free(client);

View File

@@ -59,17 +59,25 @@ DWORD WINAPI wf_update_thread(LPVOID lpParam)
{
wf_update_encode(wfi);
printf("Start of parallel sending\n");
for (index = 0; index < wfi->peerCount; index++)
{
if (wfi->peers[index]->activated)
{
printf("Setting event for %d of %d\n", index + 1, wfi->activePeerCount);
SetEvent(((wfPeerContext*) wfi->peers[index]->context)->updateEvent);
}
}
for (index = 0; index < wfi->activePeerCount; index++)
{
printf("Waiting for %d of %d\n", index + 1, wfi->activePeerCount);
WaitForSingleObject(wfi->updateSemaphore, INFINITE);
}
printf("End of parallel sending\n");
wf_info_clear_invalid_region(wfi);
}
}
@@ -107,7 +115,6 @@ void wf_update_encode(wfInfo* wfi)
width = (wfi->invalid.right - wfi->invalid.left) + 1;
height = (wfi->invalid.bottom - wfi->invalid.top) + 1;
stream_clear(wfi->s);
stream_set_pos(wfi->s, 0);
rect.x = 0;
@@ -122,6 +129,8 @@ void wf_update_encode(wfInfo* wfi)
rfx_compose_message(wfi->rfx_context, wfi->s, &rect, 1,
((uint8*) (changes->Userbuffer)) + offset, width, height, wfi->width * 4);
wfi->frame_idx = wfi->rfx_context->frame_idx;
cmd->destLeft = wfi->invalid.left;
cmd->destTop = wfi->invalid.top;
cmd->destRight = wfi->invalid.left + width;
@@ -138,46 +147,55 @@ void wf_update_encode(wfInfo* wfi)
void wf_update_peer_send(wfInfo* wfi, wfPeerContext* context)
{
freerdp_peer* client = ((rdpContext*) context)->peer;
/* This happens when the RemoteFX encoder state is reset */
if (wfi->frame_idx == 1)
context->frame_idx = 0;
/*
* When a new client connects, it is possible that old frames from
* from a previous encoding state remain. Those frames should be discarded
* as they will cause an error condition in mstsc.
*/
if ((context->frame_idx + 1) != wfi->frame_idx)
{
/* This frame is meant to be discarded */
if (context->frame_idx == 0)
return;
/* This is an unexpected error condition */
printf("Unexpected Frame Index: Actual: %d Expected: %d\n",
wfi->frame_idx, context->frame_idx + 1);
}
wfi->cmd.codecID = client->settings->rfx_codec_id;
client->update->SurfaceBits(client->update->context, &wfi->cmd);
context->frame_idx++;
}
void wf_update_encoder_init(wfInfo* wfi)
{
wfi->rfx_context = rfx_context_new();
wfi->rfx_context->mode = RLGR3;
wfi->rfx_context->width = wfi->width;
wfi->rfx_context->height = wfi->height;
rfx_context_set_pixel_format(wfi->rfx_context, RDP_PIXEL_FORMAT_B8G8R8A8);
wfi->s = stream_new(0xFFFF);
}
void wf_update_encoder_uninit(wfInfo* wfi)
{
if (wfi->rfx_context != NULL)
{
rfx_context_free(wfi->rfx_context);
wfi->rfx_context = NULL;
stream_free(wfi->s);
}
}
void wf_update_encoder_reinit(wfInfo* wfi)
void wf_update_encoder_reset(wfInfo* wfi)
{
if (wf_info_lock(wfi) > 0)
{
if (wfi->rfx_context != NULL)
rfx_context_free(wfi->rfx_context);
printf("Resetting encoder\n");
wfi->rfx_context = rfx_context_new();
wfi->rfx_context->mode = RLGR3;
wfi->rfx_context->width = wfi->width;
wfi->rfx_context->height = wfi->height;
rfx_context_set_pixel_format(wfi->rfx_context, RDP_PIXEL_FORMAT_B8G8R8A8);
if (!wfi->s)
if (wfi->rfx_context)
{
rfx_context_reset(wfi->rfx_context);
}
else
{
wfi->rfx_context = rfx_context_new();
wfi->rfx_context->mode = RLGR3;
wfi->rfx_context->width = wfi->width;
wfi->rfx_context->height = wfi->height;
rfx_context_set_pixel_format(wfi->rfx_context, RDP_PIXEL_FORMAT_B8G8R8A8);
wfi->s = stream_new(0xFFFF);
}
wf_info_invalidate_full_screen(wfi);
@@ -195,7 +213,7 @@ void wf_update_peer_activate(wfInfo* wfi, wfPeerContext* context)
ResumeThread(wfi->updateThread);
}
wf_update_encoder_reinit(wfi);
wf_update_encoder_reset(wfi);
wfi->activePeerCount++;
printf("Activating Peer Updates: %d\n", wfi->activePeerCount);