2012-09-06 04:03:07 +04:00
|
|
|
/**
|
2019-11-06 17:24:51 +03:00
|
|
|
* 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.
|
|
|
|
*/
|
2012-09-06 04:03:07 +04:00
|
|
|
|
2022-02-16 13:20:38 +03:00
|
|
|
#include <freerdp/config.h>
|
2012-09-06 04:03:07 +04:00
|
|
|
|
2012-09-29 02:10:37 +04:00
|
|
|
#include <stdio.h>
|
|
|
|
|
2012-09-07 08:01:16 +04:00
|
|
|
#include <winpr/windows.h>
|
|
|
|
|
2012-09-06 04:03:07 +04:00
|
|
|
#include <freerdp/freerdp.h>
|
|
|
|
#include <freerdp/listener.h>
|
|
|
|
|
|
|
|
#include "wf_peer.h"
|
2012-09-16 06:19:26 +04:00
|
|
|
#include "wf_info.h"
|
2012-09-06 04:03:07 +04:00
|
|
|
#include "wf_mirage.h"
|
|
|
|
|
|
|
|
#include "wf_update.h"
|
|
|
|
|
2022-04-28 06:43:31 +03:00
|
|
|
#include <freerdp/log.h>
|
2017-02-20 15:50:23 +03:00
|
|
|
#define TAG SERVER_TAG("windows")
|
|
|
|
|
2012-09-07 08:01:16 +04:00
|
|
|
DWORD WINAPI wf_update_thread(LPVOID lpParam)
|
|
|
|
{
|
2012-09-08 00:48:30 +04:00
|
|
|
int index;
|
2012-10-07 01:09:53 +04:00
|
|
|
int peerindex;
|
2012-09-07 08:01:16 +04:00
|
|
|
DWORD fps;
|
|
|
|
wfInfo* wfi;
|
|
|
|
DWORD beg, end;
|
|
|
|
DWORD diff, rate;
|
2019-11-06 17:24:51 +03:00
|
|
|
wfi = (wfInfo*)lpParam;
|
2012-09-07 20:01:36 +04:00
|
|
|
fps = wfi->framesPerSecond;
|
|
|
|
rate = 1000 / fps;
|
|
|
|
|
2012-09-07 08:01:16 +04:00
|
|
|
while (1)
|
|
|
|
{
|
|
|
|
beg = GetTickCount();
|
|
|
|
|
|
|
|
if (wf_info_lock(wfi) > 0)
|
|
|
|
{
|
2012-09-17 05:05:51 +04:00
|
|
|
if (wfi->activePeerCount > 0)
|
2012-09-07 08:01:16 +04:00
|
|
|
{
|
|
|
|
wf_info_update_changes(wfi);
|
|
|
|
|
|
|
|
if (wf_info_have_updates(wfi))
|
|
|
|
{
|
|
|
|
wf_update_encode(wfi);
|
2019-11-06 17:24:51 +03:00
|
|
|
// WLog_DBG(TAG, "Start of parallel sending");
|
2012-10-08 23:46:01 +04:00
|
|
|
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
|
|
|
{
|
2018-11-14 17:13:11 +03:00
|
|
|
for (; index < FREERDP_SERVER_WIN_INFO_MAXPEERS; index++)
|
2012-09-17 07:09:36 +04:00
|
|
|
{
|
2012-10-07 01:09:53 +04:00
|
|
|
if (wfi->peers[index] && wfi->peers[index]->activated)
|
|
|
|
{
|
2019-11-06 17:24:51 +03:00
|
|
|
// WLog_DBG(TAG, "Setting event for %d of %d", index + 1,
|
|
|
|
// wfi->activePeerCount);
|
|
|
|
SetEvent(((wfPeerContext*)wfi->peers[index]->context)->updateEvent);
|
2012-10-07 01:09:53 +04:00
|
|
|
}
|
2012-09-17 07:09:36 +04:00
|
|
|
}
|
2012-09-17 05:05:51 +04:00
|
|
|
}
|
|
|
|
|
|
|
|
for (index = 0; index < wfi->activePeerCount; index++)
|
|
|
|
{
|
2019-11-06 17:24:51 +03:00
|
|
|
// WLog_DBG(TAG, "Waiting for %d of %d", index + 1, wfi->activePeerCount);
|
|
|
|
// WaitForSingleObject(wfi->updateSemaphore, INFINITE);
|
2013-02-27 04:25:48 +04:00
|
|
|
WaitForSingleObject(wfi->updateSemaphore, 1000);
|
2012-09-17 05:05:51 +04:00
|
|
|
}
|
2012-09-08 00:48:30 +04:00
|
|
|
|
2019-11-06 17:24:51 +03:00
|
|
|
// WLog_DBG(TAG, "End of parallel sending");
|
2012-09-17 05:50:15 +04:00
|
|
|
wf_info_clear_invalid_region(wfi);
|
2012-09-07 08:01:16 +04:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
wf_info_unlock(wfi);
|
|
|
|
}
|
|
|
|
|
|
|
|
end = GetTickCount();
|
|
|
|
diff = end - beg;
|
|
|
|
|
|
|
|
if (diff < rate)
|
|
|
|
{
|
|
|
|
Sleep(rate - diff);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2019-11-06 17:24:51 +03:00
|
|
|
// WLog_DBG(TAG, "Exiting Update Thread");
|
2012-09-07 08:01:16 +04:00
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
2012-09-06 04:03:07 +04:00
|
|
|
void wf_update_encode(wfInfo* wfi)
|
|
|
|
{
|
|
|
|
RFX_RECT rect;
|
|
|
|
long height, width;
|
2012-10-09 11:01:37 +04:00
|
|
|
BYTE* pDataBits = NULL;
|
2012-09-18 22:07:38 +04:00
|
|
|
int stride;
|
2012-09-06 04:03:07 +04:00
|
|
|
SURFACE_BITS_COMMAND* cmd;
|
|
|
|
wf_info_find_invalid_region(wfi);
|
|
|
|
cmd = &wfi->cmd;
|
2013-04-30 06:35:15 +04:00
|
|
|
Stream_SetPosition(wfi->s, 0);
|
2012-09-19 01:25:20 +04:00
|
|
|
wf_info_getScreenData(wfi, &width, &height, &pDataBits, &stride);
|
2012-09-06 04:03:07 +04:00
|
|
|
rect.x = 0;
|
|
|
|
rect.y = 0;
|
2019-11-06 17:24:51 +03:00
|
|
|
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);
|
2014-03-01 00:27:05 +04:00
|
|
|
|
2019-11-06 17:24:51 +03:00
|
|
|
if (!(rfx_compose_message(wfi->rfx_context, wfi->s, &rect, 1, pDataBits, width, height,
|
|
|
|
stride)))
|
2015-04-23 16:42:21 +03:00
|
|
|
{
|
|
|
|
return;
|
|
|
|
}
|
2012-09-06 04:03:07 +04:00
|
|
|
|
2023-04-05 14:47:59 +03:00
|
|
|
wfi->frame_idx = rfx_context_get_frame_idx(wfi->rfx_context);
|
2012-09-06 04:03:07 +04:00
|
|
|
cmd->destLeft = wfi->invalid.left;
|
|
|
|
cmd->destTop = wfi->invalid.top;
|
|
|
|
cmd->destRight = wfi->invalid.left + width;
|
|
|
|
cmd->destBottom = wfi->invalid.top + height;
|
2018-11-14 17:13:11 +03:00
|
|
|
cmd->bmp.bpp = 32;
|
|
|
|
cmd->bmp.codecID = 3;
|
|
|
|
cmd->bmp.width = width;
|
|
|
|
cmd->bmp.height = height;
|
|
|
|
cmd->bmp.bitmapDataLength = Stream_GetPosition(wfi->s);
|
|
|
|
cmd->bmp.bitmapData = Stream_Buffer(wfi->s);
|
2012-09-06 04:03:07 +04:00
|
|
|
}
|
|
|
|
|
2012-09-08 00:48:30 +04:00
|
|
|
void wf_update_peer_send(wfInfo* wfi, wfPeerContext* context)
|
2012-09-06 04:03:07 +04:00
|
|
|
{
|
2022-03-23 15:18:35 +03:00
|
|
|
freerdp_peer* client;
|
|
|
|
|
|
|
|
WINPR_ASSERT(wfi);
|
|
|
|
WINPR_ASSERT(context);
|
|
|
|
|
|
|
|
client = ((rdpContext*)context)->peer;
|
|
|
|
WINPR_ASSERT(client);
|
2012-09-17 05:05:51 +04:00
|
|
|
|
2012-09-17 07:09:36 +04:00
|
|
|
/* This happens when the RemoteFX encoder state is reset */
|
2012-09-17 05:05:51 +04:00
|
|
|
|
2012-09-17 07:09:36 +04:00
|
|
|
if (wfi->frame_idx == 1)
|
|
|
|
context->frame_idx = 0;
|
|
|
|
|
|
|
|
/*
|
2019-11-06 17:24:51 +03:00
|
|
|
* 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.
|
|
|
|
*/
|
2012-09-17 07:09:36 +04:00
|
|
|
|
|
|
|
if ((context->frame_idx + 1) != wfi->frame_idx)
|
2012-09-17 05:05:51 +04:00
|
|
|
{
|
2012-09-17 07:09:36 +04:00
|
|
|
/* This frame is meant to be discarded */
|
|
|
|
if (context->frame_idx == 0)
|
|
|
|
return;
|
|
|
|
|
|
|
|
/* This is an unexpected error condition */
|
2019-11-06 17:24:51 +03:00
|
|
|
WLog_DBG(TAG, "Unexpected Frame Index: Actual: %d Expected: %d", wfi->frame_idx,
|
|
|
|
context->frame_idx + 1);
|
2012-09-17 05:05:51 +04:00
|
|
|
}
|
2012-09-17 07:09:36 +04:00
|
|
|
|
2022-03-23 15:18:35 +03:00
|
|
|
WINPR_ASSERT(client->context);
|
|
|
|
WINPR_ASSERT(client->context->settings);
|
|
|
|
WINPR_ASSERT(client->context->update);
|
|
|
|
WINPR_ASSERT(client->context->update->SurfaceBits);
|
|
|
|
|
|
|
|
wfi->cmd.bmp.codecID = client->context->settings->RemoteFxCodecId;
|
|
|
|
client->context->update->SurfaceBits(client->context, &wfi->cmd);
|
2012-09-17 07:09:36 +04:00
|
|
|
context->frame_idx++;
|
2012-09-17 05:05:51 +04:00
|
|
|
}
|
|
|
|
|
2012-09-17 07:09:36 +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
|
|
|
|
2012-09-17 07:09:36 +04:00
|
|
|
if (wfi->rfx_context)
|
|
|
|
{
|
2017-02-20 15:50:23 +03:00
|
|
|
rfx_context_reset(wfi->rfx_context, wfi->servscreen_width, wfi->servscreen_height);
|
2012-09-17 07:09:36 +04:00
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
2021-03-12 18:54:45 +03:00
|
|
|
/* TODO: pass ThreadingFlags somehow */
|
2021-03-30 11:03:15 +03:00
|
|
|
wfi->rfx_context = rfx_context_new(TRUE);
|
2023-04-05 14:47:59 +03:00
|
|
|
rfx_context_set_mode(wfi->rfx_context, RLGR3);
|
|
|
|
rfx_context_reset(wfi->rfx_context, wfi->servscreen_width, wfi->servscreen_height);
|
2017-02-20 15:50:23 +03:00
|
|
|
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 07:09:36 +04:00
|
|
|
}
|
2012-09-17 05:05:51 +04:00
|
|
|
|
2012-09-17 05:50:15 +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)
|
|
|
|
{
|
2014-07-18 02:27:40 +04:00
|
|
|
#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);
|
|
|
|
}
|
|
|
|
|
2012-09-17 07:09:36 +04:00
|
|
|
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)
|
|
|
|
{
|
2019-11-06 17:24:51 +03:00
|
|
|
freerdp_peer* client = ((rdpContext*)context)->peer;
|
2012-09-17 05:50:15 +04:00
|
|
|
|
|
|
|
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
|
|
|
|
2012-10-09 10:31:28 +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);
|
|
|
|
}
|
|
|
|
}
|