FreeRDP/server/Windows/wf_update.c

241 lines
5.7 KiB
C
Raw Normal View History

/**
* FreeRDP: A Remote Desktop Protocol Client
* FreeRDP Windows Server
*
* Copyright 2012 Marc-Andre Moreau <marcandre.moreau@gmail.com>
* Copyright 2012 Corey Clayton <can.of.tuna@gmail.com>
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
#ifdef HAVE_CONFIG_H
#include "config.h"
#endif
2012-09-29 02:10:37 +04:00
#include <stdio.h>
#include <winpr/windows.h>
#include <freerdp/freerdp.h>
#include <freerdp/listener.h>
#include "wf_peer.h"
#include "wf_info.h"
#include "wf_mirage.h"
#include "wf_update.h"
#define TAG SERVER_TAG("windows")
DWORD WINAPI wf_update_thread(LPVOID lpParam)
{
int index;
2012-10-07 01:09:53 +04:00
int peerindex;
DWORD fps;
wfInfo* wfi;
DWORD beg, end;
DWORD diff, rate;
wfi = (wfInfo*) lpParam;
fps = wfi->framesPerSecond;
rate = 1000 / fps;
while (1)
{
beg = GetTickCount();
if (wf_info_lock(wfi) > 0)
{
2012-09-17 05:05:51 +04:00
if (wfi->activePeerCount > 0)
{
wf_info_update_changes(wfi);
if (wf_info_have_updates(wfi))
{
wf_update_encode(wfi);
2014-09-12 19:38:12 +04:00
//WLog_DBG(TAG, "Start of parallel sending");
index = 0;
2016-10-04 17:54:11 +03:00
2012-10-07 01:09:53 +04:00
for (peerindex = 0; peerindex < wfi->peerCount; peerindex++)
2012-09-17 05:05:51 +04:00
{
for (; index < WF_INFO_MAXPEERS; index++)
{
2012-10-07 01:09:53 +04:00
if (wfi->peers[index] && wfi->peers[index]->activated)
{
2014-09-12 19:38:12 +04:00
//WLog_DBG(TAG, "Setting event for %d of %d", index + 1, wfi->activePeerCount);
2012-10-07 01:09:53 +04:00
SetEvent(((wfPeerContext*) wfi->peers[index]->context)->updateEvent);
}
}
2012-09-17 05:05:51 +04:00
}
for (index = 0; index < wfi->activePeerCount; index++)
{
2014-09-12 19:38:12 +04:00
//WLog_DBG(TAG, "Waiting for %d of %d", index + 1, wfi->activePeerCount);
//WaitForSingleObject(wfi->updateSemaphore, INFINITE);
WaitForSingleObject(wfi->updateSemaphore, 1000);
2012-09-17 05:05:51 +04:00
}
2014-09-12 19:38:12 +04:00
//WLog_DBG(TAG, "End of parallel sending");
wf_info_clear_invalid_region(wfi);
}
}
wf_info_unlock(wfi);
}
end = GetTickCount();
diff = end - beg;
if (diff < rate)
{
Sleep(rate - diff);
}
}
2014-09-12 19:38:12 +04:00
//WLog_DBG(TAG, "Exiting Update Thread");
return 0;
}
void wf_update_encode(wfInfo* wfi)
{
RFX_RECT rect;
long height, width;
BYTE* pDataBits = NULL;
int stride;
SURFACE_BITS_COMMAND* cmd;
wf_info_find_invalid_region(wfi);
cmd = &wfi->cmd;
Stream_SetPosition(wfi->s, 0);
2012-09-19 01:25:20 +04:00
wf_info_getScreenData(wfi, &width, &height, &pDataBits, &stride);
rect.x = 0;
rect.y = 0;
rect.width = (UINT16) width;
rect.height = (UINT16) height;
//WLog_DBG(TAG, "x:%"PRId32" y:%"PRId32" w:%ld h:%ld", wfi->invalid.left, wfi->invalid.top, width, height);
2013-05-02 02:15:55 +04:00
Stream_Clear(wfi->s);
codec/rfx: error checking and various fixes - removed some unneeded null checks for free() - fixed a memory leak in shadow_client - removed rfx_compose_message_header from API Changed the following functions to BOOL, check the result where they are called and handle failures: - rfx_compose_message - rfx_compose_message_header - rfx_write_tile - rfx_write_message_tileset - rfx_write_message_frame_begin - rfx_write_message_region - rfx_write_message_frame_end - rfx_write_message rfx_process_message: - check memory allocation failures - verify protocol-conform order of data messages to prevents memory leaks caused by repeated allocations - verify that header messages were parsed/received before the data messages - treat unknown rlgr mode as error - fixed/added error handling - fixed all callers to check/handle result rfx_encode_message: - fixed incorrect usage of realloc - missing malloc check - missing check of CreateThreadpoolWork - correct cleanup on failure (threadpool, memory) - check rfx_encode_message result rfx_encode_messages: - check rfx_split_message result - correct cleanup on failure - prevent memory leak on failure rfx_write_message_context: - fixed invalid channelId value (must be 0xFF for WBT_CONTEXT) rfx_process_message_codec_versions: - fixed invalid read size of codec_version (it is 16bit) rfx_process_message_channels: - verify protocol conform channelId value rfx_process_message_region: - replaced invalid reallocs with malloc - read and verify regionType and numTileSets from stream rfx_process_message_tileset: - check allocation results - fixed incorrect usages of realloc setupWorkers: - fixed incorrect usages of realloc rfx_split_message: - removed dead code - missing malloc check rfx_compose_message: - fixed a memory leak - check/handle rfx_encode_message result
2015-04-23 16:42:21 +03:00
if (!(rfx_compose_message(wfi->rfx_context, wfi->s, &rect, 1,
2016-10-04 17:54:11 +03:00
pDataBits, width, height, stride)))
codec/rfx: error checking and various fixes - removed some unneeded null checks for free() - fixed a memory leak in shadow_client - removed rfx_compose_message_header from API Changed the following functions to BOOL, check the result where they are called and handle failures: - rfx_compose_message - rfx_compose_message_header - rfx_write_tile - rfx_write_message_tileset - rfx_write_message_frame_begin - rfx_write_message_region - rfx_write_message_frame_end - rfx_write_message rfx_process_message: - check memory allocation failures - verify protocol-conform order of data messages to prevents memory leaks caused by repeated allocations - verify that header messages were parsed/received before the data messages - treat unknown rlgr mode as error - fixed/added error handling - fixed all callers to check/handle result rfx_encode_message: - fixed incorrect usage of realloc - missing malloc check - missing check of CreateThreadpoolWork - correct cleanup on failure (threadpool, memory) - check rfx_encode_message result rfx_encode_messages: - check rfx_split_message result - correct cleanup on failure - prevent memory leak on failure rfx_write_message_context: - fixed invalid channelId value (must be 0xFF for WBT_CONTEXT) rfx_process_message_codec_versions: - fixed invalid read size of codec_version (it is 16bit) rfx_process_message_channels: - verify protocol conform channelId value rfx_process_message_region: - replaced invalid reallocs with malloc - read and verify regionType and numTileSets from stream rfx_process_message_tileset: - check allocation results - fixed incorrect usages of realloc setupWorkers: - fixed incorrect usages of realloc rfx_split_message: - removed dead code - missing malloc check rfx_compose_message: - fixed a memory leak - check/handle rfx_encode_message result
2015-04-23 16:42:21 +03:00
{
return;
}
2013-08-14 01:18:59 +04:00
wfi->frame_idx = wfi->rfx_context->frameIdx;
cmd->destLeft = wfi->invalid.left;
cmd->destTop = wfi->invalid.top;
cmd->destRight = wfi->invalid.left + width;
cmd->destBottom = wfi->invalid.top + height;
cmd->bpp = 32;
cmd->codecID = 3;
cmd->width = width;
cmd->height = height;
cmd->bitmapDataLength = Stream_GetPosition(wfi->s);
2013-05-09 00:27:21 +04:00
cmd->bitmapData = Stream_Buffer(wfi->s);
}
void wf_update_peer_send(wfInfo* wfi, wfPeerContext* context)
{
freerdp_peer* client = ((rdpContext*) context)->peer;
2012-09-17 05:05:51 +04:00
/* This happens when the RemoteFX encoder state is reset */
2012-09-17 05:05:51 +04:00
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)
2012-09-17 05:05:51 +04:00
{
/* This frame is meant to be discarded */
if (context->frame_idx == 0)
return;
/* This is an unexpected error condition */
2014-09-12 19:38:12 +04:00
WLog_DBG(TAG, "Unexpected Frame Index: Actual: %d Expected: %d",
2016-10-04 17:54:11 +03:00
wfi->frame_idx, context->frame_idx + 1);
2012-09-17 05:05:51 +04:00
}
wfi->cmd.codecID = client->settings->RemoteFxCodecId;
client->update->SurfaceBits(client->update->context, &wfi->cmd);
context->frame_idx++;
2012-09-17 05:05:51 +04:00
}
void wf_update_encoder_reset(wfInfo* wfi)
2012-09-17 05:05:51 +04:00
{
if (wf_info_lock(wfi) > 0)
{
2014-09-12 19:38:12 +04:00
WLog_DBG(TAG, "Resetting encoder");
2012-09-17 05:05:51 +04:00
if (wfi->rfx_context)
{
rfx_context_reset(wfi->rfx_context, wfi->servscreen_width, wfi->servscreen_height);
}
else
{
wfi->rfx_context = rfx_context_new(TRUE);
wfi->rfx_context->mode = RLGR3;
wfi->rfx_context->width = wfi->servscreen_width;
wfi->rfx_context->height = wfi->servscreen_height;
rfx_context_set_pixel_format(wfi->rfx_context, PIXEL_FORMAT_BGRA32);
2013-05-09 01:48:30 +04:00
wfi->s = Stream_New(NULL, 0xFFFF);
}
2012-09-17 05:05:51 +04:00
wf_info_invalidate_full_screen(wfi);
2012-09-17 05:05:51 +04:00
wf_info_unlock(wfi);
}
}
void wf_update_peer_activate(wfInfo* wfi, wfPeerContext* context)
{
if (wf_info_lock(wfi) > 0)
{
if (wfi->activePeerCount < 1)
{
#ifndef WITH_DXGI_1_2
2012-09-19 21:34:37 +04:00
wf_mirror_driver_activate(wfi);
#endif
2012-09-17 05:05:51 +04:00
ResumeThread(wfi->updateThread);
}
wf_update_encoder_reset(wfi);
2012-09-17 05:05:51 +04:00
wfi->activePeerCount++;
2014-09-12 19:38:12 +04:00
WLog_DBG(TAG, "Activating Peer Updates: %d", wfi->activePeerCount);
2012-09-17 05:05:51 +04:00
wf_info_unlock(wfi);
}
}
void wf_update_peer_deactivate(wfInfo* wfi, wfPeerContext* context)
{
if (wf_info_lock(wfi) > 0)
{
freerdp_peer* client = ((rdpContext*) context)->peer;
if (client->activated)
2012-09-17 05:05:51 +04:00
{
2012-09-19 21:42:22 +04:00
if (wfi->activePeerCount <= 1)
{
wf_mirror_driver_deactivate(wfi);
}
2012-09-17 05:05:51 +04:00
client->activated = FALSE;
2012-09-17 05:05:51 +04:00
wfi->activePeerCount--;
2014-09-12 19:38:12 +04:00
WLog_DBG(TAG, "Deactivating Peer Updates: %d", wfi->activePeerCount);
2012-09-17 05:05:51 +04:00
}
wf_info_unlock(wfi);
}
}