Blame server/Windows/wf_update.c

Packit 1fb8d4
/**
Packit 1fb8d4
* FreeRDP: A Remote Desktop Protocol Client
Packit 1fb8d4
* FreeRDP Windows Server
Packit 1fb8d4
*
Packit 1fb8d4
* Copyright 2012 Marc-Andre Moreau <marcandre.moreau@gmail.com>
Packit 1fb8d4
* Copyright 2012 Corey Clayton <can.of.tuna@gmail.com>
Packit 1fb8d4
*
Packit 1fb8d4
* Licensed under the Apache License, Version 2.0 (the "License");
Packit 1fb8d4
* you may not use this file except in compliance with the License.
Packit 1fb8d4
* You may obtain a copy of the License at
Packit 1fb8d4
*
Packit 1fb8d4
*     http://www.apache.org/licenses/LICENSE-2.0
Packit 1fb8d4
*
Packit 1fb8d4
* Unless required by applicable law or agreed to in writing, software
Packit 1fb8d4
* distributed under the License is distributed on an "AS IS" BASIS,
Packit 1fb8d4
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
Packit 1fb8d4
* See the License for the specific language governing permissions and
Packit 1fb8d4
* limitations under the License.
Packit 1fb8d4
*/
Packit 1fb8d4
Packit 1fb8d4
#ifdef HAVE_CONFIG_H
Packit 1fb8d4
#include "config.h"
Packit 1fb8d4
#endif
Packit 1fb8d4
Packit 1fb8d4
#include <stdio.h>
Packit 1fb8d4
Packit 1fb8d4
#include <winpr/windows.h>
Packit 1fb8d4
Packit 1fb8d4
#include <freerdp/freerdp.h>
Packit 1fb8d4
#include <freerdp/listener.h>
Packit 1fb8d4
Packit 1fb8d4
#include "wf_peer.h"
Packit 1fb8d4
#include "wf_info.h"
Packit 1fb8d4
#include "wf_mirage.h"
Packit 1fb8d4
Packit 1fb8d4
#include "wf_update.h"
Packit 1fb8d4
Packit 1fb8d4
#define TAG SERVER_TAG("windows")
Packit 1fb8d4
Packit 1fb8d4
DWORD WINAPI wf_update_thread(LPVOID lpParam)
Packit 1fb8d4
{
Packit 1fb8d4
	int index;
Packit 1fb8d4
	int peerindex;
Packit 1fb8d4
	DWORD fps;
Packit 1fb8d4
	wfInfo* wfi;
Packit 1fb8d4
	DWORD beg, end;
Packit 1fb8d4
	DWORD diff, rate;
Packit 1fb8d4
	wfi = (wfInfo*) lpParam;
Packit 1fb8d4
	fps = wfi->framesPerSecond;
Packit 1fb8d4
	rate = 1000 / fps;
Packit 1fb8d4
Packit 1fb8d4
	while (1)
Packit 1fb8d4
	{
Packit 1fb8d4
		beg = GetTickCount();
Packit 1fb8d4
Packit 1fb8d4
		if (wf_info_lock(wfi) > 0)
Packit 1fb8d4
		{
Packit 1fb8d4
			if (wfi->activePeerCount > 0)
Packit 1fb8d4
			{
Packit 1fb8d4
				wf_info_update_changes(wfi);
Packit 1fb8d4
Packit 1fb8d4
				if (wf_info_have_updates(wfi))
Packit 1fb8d4
				{
Packit 1fb8d4
					wf_update_encode(wfi);
Packit 1fb8d4
					//WLog_DBG(TAG, "Start of parallel sending");
Packit 1fb8d4
					index = 0;
Packit 1fb8d4
Packit 1fb8d4
					for (peerindex = 0; peerindex < wfi->peerCount; peerindex++)
Packit 1fb8d4
					{
Packit 1fb8d4
						for (; index < WF_INFO_MAXPEERS; index++)
Packit 1fb8d4
						{
Packit 1fb8d4
							if (wfi->peers[index] && wfi->peers[index]->activated)
Packit 1fb8d4
							{
Packit 1fb8d4
								//WLog_DBG(TAG, "Setting event for %d of %d", index + 1, wfi->activePeerCount);
Packit 1fb8d4
								SetEvent(((wfPeerContext*) wfi->peers[index]->context)->updateEvent);
Packit 1fb8d4
							}
Packit 1fb8d4
						}
Packit 1fb8d4
					}
Packit 1fb8d4
Packit 1fb8d4
					for (index = 0; index < wfi->activePeerCount; index++)
Packit 1fb8d4
					{
Packit 1fb8d4
						//WLog_DBG(TAG, "Waiting for %d of %d", index + 1, wfi->activePeerCount);
Packit 1fb8d4
						//WaitForSingleObject(wfi->updateSemaphore, INFINITE);
Packit 1fb8d4
						WaitForSingleObject(wfi->updateSemaphore, 1000);
Packit 1fb8d4
					}
Packit 1fb8d4
Packit 1fb8d4
					//WLog_DBG(TAG, "End of parallel sending");
Packit 1fb8d4
					wf_info_clear_invalid_region(wfi);
Packit 1fb8d4
				}
Packit 1fb8d4
			}
Packit 1fb8d4
Packit 1fb8d4
			wf_info_unlock(wfi);
Packit 1fb8d4
		}
Packit 1fb8d4
Packit 1fb8d4
		end = GetTickCount();
Packit 1fb8d4
		diff = end - beg;
Packit 1fb8d4
Packit 1fb8d4
		if (diff < rate)
Packit 1fb8d4
		{
Packit 1fb8d4
			Sleep(rate - diff);
Packit 1fb8d4
		}
Packit 1fb8d4
	}
Packit 1fb8d4
Packit 1fb8d4
	//WLog_DBG(TAG, "Exiting Update Thread");
Packit 1fb8d4
	return 0;
Packit 1fb8d4
}
Packit 1fb8d4
Packit 1fb8d4
void wf_update_encode(wfInfo* wfi)
Packit 1fb8d4
{
Packit 1fb8d4
	RFX_RECT rect;
Packit 1fb8d4
	long height, width;
Packit 1fb8d4
	BYTE* pDataBits = NULL;
Packit 1fb8d4
	int stride;
Packit 1fb8d4
	SURFACE_BITS_COMMAND* cmd;
Packit 1fb8d4
	wf_info_find_invalid_region(wfi);
Packit 1fb8d4
	cmd = &wfi->cmd;
Packit 1fb8d4
	Stream_SetPosition(wfi->s, 0);
Packit 1fb8d4
	wf_info_getScreenData(wfi, &width, &height, &pDataBits, &stride);
Packit 1fb8d4
	rect.x = 0;
Packit 1fb8d4
	rect.y = 0;
Packit 1fb8d4
	rect.width = (UINT16) width;
Packit 1fb8d4
	rect.height = (UINT16) height;
Packit 1fb8d4
	//WLog_DBG(TAG, "x:%"PRId32" y:%"PRId32" w:%ld h:%ld", wfi->invalid.left, wfi->invalid.top, width, height);
Packit 1fb8d4
	Stream_Clear(wfi->s);
Packit 1fb8d4
Packit 1fb8d4
	if (!(rfx_compose_message(wfi->rfx_context, wfi->s, &rect, 1,
Packit 1fb8d4
	                          pDataBits, width, height, stride)))
Packit 1fb8d4
	{
Packit 1fb8d4
		return;
Packit 1fb8d4
	}
Packit 1fb8d4
Packit 1fb8d4
	wfi->frame_idx = wfi->rfx_context->frameIdx;
Packit 1fb8d4
	cmd->destLeft = wfi->invalid.left;
Packit 1fb8d4
	cmd->destTop = wfi->invalid.top;
Packit 1fb8d4
	cmd->destRight = wfi->invalid.left + width;
Packit 1fb8d4
	cmd->destBottom = wfi->invalid.top + height;
Packit 1fb8d4
	cmd->bpp = 32;
Packit 1fb8d4
	cmd->codecID = 3;
Packit 1fb8d4
	cmd->width = width;
Packit 1fb8d4
	cmd->height = height;
Packit 1fb8d4
	cmd->bitmapDataLength = Stream_GetPosition(wfi->s);
Packit 1fb8d4
	cmd->bitmapData = Stream_Buffer(wfi->s);
Packit 1fb8d4
}
Packit 1fb8d4
Packit 1fb8d4
void wf_update_peer_send(wfInfo* wfi, wfPeerContext* context)
Packit 1fb8d4
{
Packit 1fb8d4
	freerdp_peer* client = ((rdpContext*) context)->peer;
Packit 1fb8d4
Packit 1fb8d4
	/* This happens when the RemoteFX encoder state is reset */
Packit 1fb8d4
Packit 1fb8d4
	if (wfi->frame_idx == 1)
Packit 1fb8d4
		context->frame_idx = 0;
Packit 1fb8d4
Packit 1fb8d4
	/*
Packit 1fb8d4
	* When a new client connects, it is possible that old frames from
Packit 1fb8d4
	* from a previous encoding state remain. Those frames should be discarded
Packit 1fb8d4
	* as they will cause an error condition in mstsc.
Packit 1fb8d4
	*/
Packit 1fb8d4
Packit 1fb8d4
	if ((context->frame_idx + 1) != wfi->frame_idx)
Packit 1fb8d4
	{
Packit 1fb8d4
		/* This frame is meant to be discarded */
Packit 1fb8d4
		if (context->frame_idx == 0)
Packit 1fb8d4
			return;
Packit 1fb8d4
Packit 1fb8d4
		/* This is an unexpected error condition */
Packit 1fb8d4
		WLog_DBG(TAG, "Unexpected Frame Index: Actual: %d Expected: %d",
Packit 1fb8d4
		         wfi->frame_idx, context->frame_idx + 1);
Packit 1fb8d4
	}
Packit 1fb8d4
Packit 1fb8d4
	wfi->cmd.codecID = client->settings->RemoteFxCodecId;
Packit 1fb8d4
	client->update->SurfaceBits(client->update->context, &wfi->cmd);
Packit 1fb8d4
	context->frame_idx++;
Packit 1fb8d4
}
Packit 1fb8d4
Packit 1fb8d4
void wf_update_encoder_reset(wfInfo* wfi)
Packit 1fb8d4
{
Packit 1fb8d4
	if (wf_info_lock(wfi) > 0)
Packit 1fb8d4
	{
Packit 1fb8d4
		WLog_DBG(TAG, "Resetting encoder");
Packit 1fb8d4
Packit 1fb8d4
		if (wfi->rfx_context)
Packit 1fb8d4
		{
Packit 1fb8d4
			rfx_context_reset(wfi->rfx_context, wfi->servscreen_width, wfi->servscreen_height);
Packit 1fb8d4
		}
Packit 1fb8d4
		else
Packit 1fb8d4
		{
Packit 1fb8d4
			wfi->rfx_context = rfx_context_new(TRUE);
Packit 1fb8d4
			wfi->rfx_context->mode = RLGR3;
Packit 1fb8d4
			wfi->rfx_context->width = wfi->servscreen_width;
Packit 1fb8d4
			wfi->rfx_context->height = wfi->servscreen_height;
Packit 1fb8d4
			rfx_context_set_pixel_format(wfi->rfx_context, PIXEL_FORMAT_BGRA32);
Packit 1fb8d4
			wfi->s = Stream_New(NULL, 0xFFFF);
Packit 1fb8d4
		}
Packit 1fb8d4
Packit 1fb8d4
		wf_info_invalidate_full_screen(wfi);
Packit 1fb8d4
		wf_info_unlock(wfi);
Packit 1fb8d4
	}
Packit 1fb8d4
}
Packit 1fb8d4
Packit 1fb8d4
void wf_update_peer_activate(wfInfo* wfi, wfPeerContext* context)
Packit 1fb8d4
{
Packit 1fb8d4
	if (wf_info_lock(wfi) > 0)
Packit 1fb8d4
	{
Packit 1fb8d4
		if (wfi->activePeerCount < 1)
Packit 1fb8d4
		{
Packit 1fb8d4
#ifndef WITH_DXGI_1_2
Packit 1fb8d4
			wf_mirror_driver_activate(wfi);
Packit 1fb8d4
#endif
Packit 1fb8d4
			ResumeThread(wfi->updateThread);
Packit 1fb8d4
		}
Packit 1fb8d4
Packit 1fb8d4
		wf_update_encoder_reset(wfi);
Packit 1fb8d4
		wfi->activePeerCount++;
Packit 1fb8d4
		WLog_DBG(TAG, "Activating Peer Updates: %d", wfi->activePeerCount);
Packit 1fb8d4
		wf_info_unlock(wfi);
Packit 1fb8d4
	}
Packit 1fb8d4
}
Packit 1fb8d4
Packit 1fb8d4
void wf_update_peer_deactivate(wfInfo* wfi, wfPeerContext* context)
Packit 1fb8d4
{
Packit 1fb8d4
	if (wf_info_lock(wfi) > 0)
Packit 1fb8d4
	{
Packit 1fb8d4
		freerdp_peer* client = ((rdpContext*) context)->peer;
Packit 1fb8d4
Packit 1fb8d4
		if (client->activated)
Packit 1fb8d4
		{
Packit 1fb8d4
			if (wfi->activePeerCount <= 1)
Packit 1fb8d4
			{
Packit 1fb8d4
				wf_mirror_driver_deactivate(wfi);
Packit 1fb8d4
			}
Packit 1fb8d4
Packit 1fb8d4
			client->activated = FALSE;
Packit 1fb8d4
			wfi->activePeerCount--;
Packit 1fb8d4
			WLog_DBG(TAG, "Deactivating Peer Updates: %d", wfi->activePeerCount);
Packit 1fb8d4
		}
Packit 1fb8d4
Packit 1fb8d4
		wf_info_unlock(wfi);
Packit 1fb8d4
	}
Packit 1fb8d4
}