Merge pull request #3316 from realjiangms/server_gfx
rdpgfx: Implementation for server side channel
This commit is contained in:
commit
5394a0425f
@ -21,3 +21,6 @@ if(WITH_CLIENT_CHANNELS)
|
||||
add_channel_client(${MODULE_PREFIX} ${CHANNEL_NAME})
|
||||
endif()
|
||||
|
||||
if(WITH_SERVER_CHANNELS)
|
||||
add_channel_server(${MODULE_PREFIX} ${CHANNEL_NAME})
|
||||
endif()
|
||||
|
@ -22,8 +22,8 @@ set(${MODULE_PREFIX}_SRCS
|
||||
rdpgfx_main.h
|
||||
rdpgfx_codec.c
|
||||
rdpgfx_codec.h
|
||||
rdpgfx_common.c
|
||||
rdpgfx_common.h)
|
||||
../rdpgfx_common.c
|
||||
../rdpgfx_common.h)
|
||||
|
||||
include_directories(..)
|
||||
|
||||
|
@ -57,7 +57,7 @@ static UINT rdpgfx_read_h264_metablock(RDPGFX_PLUGIN* gfx, wStream* s,
|
||||
|
||||
Stream_Read_UINT32(s, meta->numRegionRects); /* numRegionRects (4 bytes) */
|
||||
|
||||
if (Stream_GetRemainingLength(s) < (meta->numRegionRects * sizeof(RECTANGLE_16)))
|
||||
if (Stream_GetRemainingLength(s) < (meta->numRegionRects * 8))
|
||||
{
|
||||
WLog_ERR(TAG, "not enough data!");
|
||||
goto error_out;
|
||||
|
@ -457,7 +457,7 @@ static UINT rdpgfx_recv_start_frame_pdu(RDPGFX_CHANNEL_CALLBACK* callback, wStre
|
||||
RdpgfxClientContext* context = (RdpgfxClientContext*) gfx->iface.pInterface;
|
||||
UINT error = CHANNEL_RC_OK;
|
||||
|
||||
if (Stream_GetRemainingLength(s) < 8)
|
||||
if (Stream_GetRemainingLength(s) < RDPGFX_START_FRAME_PDU_SIZE)
|
||||
{
|
||||
WLog_ERR(TAG, "not enough data!");
|
||||
return ERROR_INVALID_DATA;
|
||||
@ -494,7 +494,7 @@ static UINT rdpgfx_recv_end_frame_pdu(RDPGFX_CHANNEL_CALLBACK* callback, wStream
|
||||
RdpgfxClientContext* context = (RdpgfxClientContext*) gfx->iface.pInterface;
|
||||
UINT error = CHANNEL_RC_OK;
|
||||
|
||||
if (Stream_GetRemainingLength(s) < 4)
|
||||
if (Stream_GetRemainingLength(s) < RDPGFX_END_FRAME_PDU_SIZE)
|
||||
{
|
||||
WLog_ERR(TAG, "not enough data!");
|
||||
return ERROR_INVALID_DATA;
|
||||
@ -550,7 +550,7 @@ static UINT rdpgfx_recv_wire_to_surface_1_pdu(RDPGFX_CHANNEL_CALLBACK* callback,
|
||||
RDPGFX_PLUGIN* gfx = (RDPGFX_PLUGIN*) callback->plugin;
|
||||
UINT error;
|
||||
|
||||
if (Stream_GetRemainingLength(s) < 17)
|
||||
if (Stream_GetRemainingLength(s) < RDPGFX_WIRE_TO_SURFACE_PDU_1_SIZE)
|
||||
{
|
||||
WLog_ERR(TAG, "not enough data!");
|
||||
return ERROR_INVALID_DATA;
|
||||
@ -615,7 +615,7 @@ static UINT rdpgfx_recv_wire_to_surface_2_pdu(RDPGFX_CHANNEL_CALLBACK* callback,
|
||||
RdpgfxClientContext* context = (RdpgfxClientContext*) gfx->iface.pInterface;
|
||||
UINT error = CHANNEL_RC_OK;
|
||||
|
||||
if (Stream_GetRemainingLength(s) < 13)
|
||||
if (Stream_GetRemainingLength(s) < RDPGFX_WIRE_TO_SURFACE_PDU_2_SIZE)
|
||||
{
|
||||
WLog_ERR(TAG, "not enough data!");
|
||||
return ERROR_INVALID_DATA;
|
||||
|
@ -54,7 +54,8 @@ const char* RDPGFX_CMDID_STRINGS[] =
|
||||
"RDPGFX_CMDID_CAPSADVERTISE",
|
||||
"RDPGFX_CMDID_CAPSCONFIRM",
|
||||
"RDPGFX_CMDID_UNUSED_0014",
|
||||
"RDPGFX_CMDID_MAPSURFACETOWINDOW"
|
||||
"RDPGFX_CMDID_MAPSURFACETOWINDOW",
|
||||
"RDPGFX_CMDID_QOEFRAMEACKNOWLEDGE"
|
||||
};
|
||||
|
||||
const char* rdpgfx_get_cmd_id_string(UINT16 cmdId)
|
34
channels/rdpgfx/server/CMakeLists.txt
Normal file
34
channels/rdpgfx/server/CMakeLists.txt
Normal file
@ -0,0 +1,34 @@
|
||||
# FreeRDP: A Remote Desktop Protocol Implementation
|
||||
# FreeRDP cmake build script
|
||||
#
|
||||
# Copyright 2016 Jiang Zihao <zihao.jiang@yahoo.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.
|
||||
|
||||
define_channel_server("rdpgfx")
|
||||
|
||||
set(${MODULE_PREFIX}_SRCS
|
||||
rdpgfx_main.c
|
||||
rdpgfx_main.h
|
||||
../rdpgfx_common.c
|
||||
../rdpgfx_common.h)
|
||||
|
||||
include_directories(..)
|
||||
|
||||
add_channel_server_library(${MODULE_PREFIX} ${MODULE_NAME} ${CHANNEL_NAME} FALSE "DVCPluginEntry")
|
||||
|
||||
|
||||
|
||||
target_link_libraries(${MODULE_NAME} freerdp)
|
||||
|
||||
set_property(TARGET ${MODULE_NAME} PROPERTY FOLDER "Channels/${CHANNEL_NAME}/Server")
|
1643
channels/rdpgfx/server/rdpgfx_main.c
Normal file
1643
channels/rdpgfx/server/rdpgfx_main.c
Normal file
File diff suppressed because it is too large
Load Diff
40
channels/rdpgfx/server/rdpgfx_main.h
Normal file
40
channels/rdpgfx/server/rdpgfx_main.h
Normal file
@ -0,0 +1,40 @@
|
||||
/**
|
||||
* FreeRDP: A Remote Desktop Protocol Implementation
|
||||
* Graphics Pipeline Extension
|
||||
*
|
||||
* Copyright 2016 Jiang Zihao <zihao.jiang@yahoo.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.
|
||||
*/
|
||||
|
||||
#ifndef FREERDP_CHANNEL_RDPGFX_SERVER_MAIN_H
|
||||
#define FREERDP_CHANNEL_RDPGFX_SERVER_MAIN_H
|
||||
|
||||
#include <freerdp/server/rdpgfx.h>
|
||||
#include <freerdp/codec/zgfx.h>
|
||||
|
||||
struct _rdpgfx_server_private
|
||||
{
|
||||
ZGFX_CONTEXT* zgfx;
|
||||
BOOL ownThread;
|
||||
HANDLE thread;
|
||||
HANDLE stopEvent;
|
||||
HANDLE channelEvent;
|
||||
void* rdpgfx_channel;
|
||||
DWORD SessionId;
|
||||
wStream* input_stream;
|
||||
BOOL isOpened;
|
||||
BOOL isReady;
|
||||
};
|
||||
|
||||
#endif /* FREERDP_CHANNEL_RDPGFX_SERVER_MAIN_H */
|
@ -49,6 +49,7 @@
|
||||
#include <freerdp/server/drdynvc.h>
|
||||
#include <freerdp/server/remdesk.h>
|
||||
#include <freerdp/server/encomsp.h>
|
||||
#include <freerdp/server/rdpgfx.h>
|
||||
|
||||
void freerdp_channels_dummy()
|
||||
{
|
||||
@ -79,6 +80,8 @@ void freerdp_channels_dummy()
|
||||
encomsp_server_context_new(NULL);
|
||||
encomsp_server_context_free(NULL);
|
||||
|
||||
rdpgfx_server_context_new(NULL);
|
||||
rdpgfx_server_context_free(NULL);
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -73,6 +73,7 @@ typedef BYTE RDPGFX_PIXELFORMAT;
|
||||
#define RDPGFX_CMDID_CAPSCONFIRM 0x0013
|
||||
#define RDPGFX_CMDID_UNUSED_0014 0x0014
|
||||
#define RDPGFX_CMDID_MAPSURFACETOWINDOW 0x0015
|
||||
#define RDPGFX_CMDID_QOEFRAMEACKNOWLEDGE 0x0016
|
||||
|
||||
#define RDPGFX_HEADER_SIZE 8
|
||||
|
||||
@ -142,6 +143,8 @@ typedef struct _RDPGFX_CAPSET_VERSION10 RDPGFX_CAPSET_VERSION10;
|
||||
#define RDPGFX_CODECID_ALPHA 0x000C
|
||||
#define RDPGFX_CODECID_AVC444 0x000E
|
||||
|
||||
#define RDPGFX_WIRE_TO_SURFACE_PDU_1_SIZE 17
|
||||
|
||||
struct _RDPGFX_WIRE_TO_SURFACE_PDU_1
|
||||
{
|
||||
UINT16 surfaceId;
|
||||
@ -156,6 +159,8 @@ typedef struct _RDPGFX_WIRE_TO_SURFACE_PDU_1 RDPGFX_WIRE_TO_SURFACE_PDU_1;
|
||||
#define RDPGFX_CODECID_CAPROGRESSIVE 0x0009
|
||||
#define RDPGFX_CODECID_CAPROGRESSIVE_V2 0x000D
|
||||
|
||||
#define RDPGFX_WIRE_TO_SURFACE_PDU_2_SIZE 13
|
||||
|
||||
struct _RDPGFX_WIRE_TO_SURFACE_PDU_2
|
||||
{
|
||||
UINT16 surfaceId;
|
||||
@ -250,6 +255,8 @@ struct _RDPGFX_DELETE_SURFACE_PDU
|
||||
};
|
||||
typedef struct _RDPGFX_DELETE_SURFACE_PDU RDPGFX_DELETE_SURFACE_PDU;
|
||||
|
||||
#define RDPGFX_START_FRAME_PDU_SIZE 8
|
||||
|
||||
struct _RDPGFX_START_FRAME_PDU
|
||||
{
|
||||
UINT32 timestamp;
|
||||
@ -257,6 +264,8 @@ struct _RDPGFX_START_FRAME_PDU
|
||||
};
|
||||
typedef struct _RDPGFX_START_FRAME_PDU RDPGFX_START_FRAME_PDU;
|
||||
|
||||
#define RDPGFX_END_FRAME_PDU_SIZE 4
|
||||
|
||||
struct _RDPGFX_END_FRAME_PDU
|
||||
{
|
||||
UINT32 frameId;
|
||||
@ -372,6 +381,14 @@ struct _RDPGFX_AVC444_BITMAP_STREAM
|
||||
};
|
||||
typedef struct _RDPGFX_AVC444_BITMAP_STREAM RDPGFX_AVC444_BITMAP_STREAM;
|
||||
|
||||
struct _RDPGFX_QOE_FRAME_ACKNOWLEDGE_PDU
|
||||
{
|
||||
UINT32 frameId;
|
||||
UINT32 timestamp;
|
||||
UINT16 timeDiffSE;
|
||||
UINT16 timeDiffEDR;
|
||||
};
|
||||
typedef struct _RDPGFX_QOE_FRAME_ACKNOWLEDGE_PDU RDPGFX_QOE_FRAME_ACKNOWLEDGE_PDU;
|
||||
|
||||
#endif /* FREERDP_CHANNEL_RDPGFX_H */
|
||||
|
||||
|
@ -43,6 +43,13 @@
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
enum
|
||||
{
|
||||
DRDYNVC_STATE_NONE = 0,
|
||||
DRDYNVC_STATE_INITIALIZED = 1,
|
||||
DRDYNVC_STATE_READY = 2
|
||||
};
|
||||
|
||||
/**
|
||||
* WTSVirtualChannelManager functions are FreeRDP extensions to the API.
|
||||
*/
|
||||
@ -51,6 +58,7 @@ FREERDP_API void WTSVirtualChannelManagerGetFileDescriptor(HANDLE hServer, void*
|
||||
FREERDP_API BOOL WTSVirtualChannelManagerCheckFileDescriptor(HANDLE hServer);
|
||||
FREERDP_API HANDLE WTSVirtualChannelManagerGetEventHandle(HANDLE hServer);
|
||||
FREERDP_API BOOL WTSVirtualChannelManagerIsChannelJoined(HANDLE hServer, const char* name);
|
||||
FREERDP_API BYTE WTSVirtualChannelManagerGetDrdynvcState(HANDLE hServer);
|
||||
|
||||
/**
|
||||
* Extended FreeRDP WTS functions for channel handling
|
||||
|
@ -28,12 +28,16 @@
|
||||
#define ZGFX_SEGMENTED_SINGLE 0xE0
|
||||
#define ZGFX_SEGMENTED_MULTIPART 0xE1
|
||||
|
||||
#define ZGFX_PACKET_COMPR_TYPE_RDP8 0x04
|
||||
|
||||
#define ZGFX_SEGMENTED_MAXSIZE 65535
|
||||
|
||||
struct _ZGFX_CONTEXT
|
||||
{
|
||||
BOOL Compressor;
|
||||
|
||||
BYTE* pbInputCurrent;
|
||||
BYTE* pbInputEnd;
|
||||
const BYTE* pbInputCurrent;
|
||||
const BYTE* pbInputEnd;
|
||||
|
||||
UINT32 bits;
|
||||
UINT32 cBitsRemaining;
|
||||
@ -53,8 +57,9 @@ typedef struct _ZGFX_CONTEXT ZGFX_CONTEXT;
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
FREERDP_API int zgfx_compress(ZGFX_CONTEXT* zgfx, BYTE* pSrcData, UINT32 SrcSize, BYTE** ppDstData, UINT32* pDstSize, UINT32* pFlags);
|
||||
FREERDP_API int zgfx_decompress(ZGFX_CONTEXT* zgfx, BYTE* pSrcData, UINT32 SrcSize, BYTE** ppDstData, UINT32* pDstSize, UINT32 flags);
|
||||
FREERDP_API int zgfx_decompress(ZGFX_CONTEXT* zgfx, const BYTE* pSrcData, UINT32 SrcSize, BYTE** ppDstData, UINT32* pDstSize, UINT32 flags);
|
||||
FREERDP_API int zgfx_compress(ZGFX_CONTEXT* zgfx, const BYTE* pSrcData, UINT32 SrcSize, BYTE** ppDstData, UINT32* pDstSize, UINT32* pFlags);
|
||||
FREERDP_API int zgfx_compress_to_stream(ZGFX_CONTEXT* zgfx, wStream* sDst, const BYTE* pUncompressed, UINT32 uncompressedSize, UINT32* pFlags);
|
||||
|
||||
FREERDP_API void zgfx_context_reset(ZGFX_CONTEXT* zgfx, BOOL flush);
|
||||
|
||||
|
100
include/freerdp/server/rdpgfx.h
Normal file
100
include/freerdp/server/rdpgfx.h
Normal file
@ -0,0 +1,100 @@
|
||||
/**
|
||||
* FreeRDP: A Remote Desktop Protocol Implementation
|
||||
* Graphics Pipeline Extension
|
||||
*
|
||||
* Copyright 2016 Jiang Zihao <zihao.jiang@yahoo.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.
|
||||
*/
|
||||
|
||||
#ifndef FREERDP_CHANNEL_SERVER_RDPGFX_H
|
||||
#define FREERDP_CHANNEL_SERVER_RDPGFX_H
|
||||
|
||||
#include <freerdp/channels/rdpgfx.h>
|
||||
|
||||
typedef struct _rdpgfx_server_context RdpgfxServerContext;
|
||||
typedef struct _rdpgfx_server_private RdpgfxServerPrivate;
|
||||
|
||||
typedef BOOL (*psRdpgfxServerOpen)(RdpgfxServerContext* context);
|
||||
typedef BOOL (*psRdpgfxServerClose)(RdpgfxServerContext* context);
|
||||
|
||||
typedef UINT(*psRdpgfxResetGraphics)(RdpgfxServerContext* context, RDPGFX_RESET_GRAPHICS_PDU* resetGraphics);
|
||||
typedef UINT(*psRdpgfxStartFrame)(RdpgfxServerContext* context, RDPGFX_START_FRAME_PDU* startFrame);
|
||||
typedef UINT(*psRdpgfxEndFrame)(RdpgfxServerContext* context, RDPGFX_END_FRAME_PDU* endFrame);
|
||||
typedef UINT(*psRdpgfxSurfaceCommand)(RdpgfxServerContext* context, RDPGFX_SURFACE_COMMAND* cmd);
|
||||
typedef UINT(*psRdpgfxSurfaceFrameCommand)(RdpgfxServerContext* context, RDPGFX_SURFACE_COMMAND* cmd, RDPGFX_START_FRAME_PDU* startFrame, RDPGFX_END_FRAME_PDU* endFrame);
|
||||
typedef UINT(*psRdpgfxDeleteEncodingContext)(RdpgfxServerContext* context, RDPGFX_DELETE_ENCODING_CONTEXT_PDU* deleteEncodingContext);
|
||||
typedef UINT(*psRdpgfxCreateSurface)(RdpgfxServerContext* context, RDPGFX_CREATE_SURFACE_PDU* createSurface);
|
||||
typedef UINT(*psRdpgfxDeleteSurface)(RdpgfxServerContext* context, RDPGFX_DELETE_SURFACE_PDU* deleteSurface);
|
||||
typedef UINT(*psRdpgfxSolidFill)(RdpgfxServerContext* context, RDPGFX_SOLID_FILL_PDU* solidFill);
|
||||
typedef UINT(*psRdpgfxSurfaceToSurface)(RdpgfxServerContext* context, RDPGFX_SURFACE_TO_SURFACE_PDU* surfaceToSurface);
|
||||
typedef UINT(*psRdpgfxSurfaceToCache)(RdpgfxServerContext* context, RDPGFX_SURFACE_TO_CACHE_PDU* surfaceToCache);
|
||||
typedef UINT(*psRdpgfxCacheToSurface)(RdpgfxServerContext* context, RDPGFX_CACHE_TO_SURFACE_PDU* cacheToSurface);
|
||||
typedef UINT(*psRdpgfxCacheImportOffer)(RdpgfxServerContext* context, RDPGFX_CACHE_IMPORT_OFFER_PDU* cacheImportOffer);
|
||||
typedef UINT(*psRdpgfxCacheImportReply)(RdpgfxServerContext* context, RDPGFX_CACHE_IMPORT_REPLY_PDU* cacheImportReply);
|
||||
typedef UINT(*psRdpgfxEvictCacheEntry)(RdpgfxServerContext* context, RDPGFX_EVICT_CACHE_ENTRY_PDU* evictCacheEntry);
|
||||
typedef UINT(*psRdpgfxMapSurfaceToOutput)(RdpgfxServerContext* context, RDPGFX_MAP_SURFACE_TO_OUTPUT_PDU* surfaceToOutput);
|
||||
typedef UINT(*psRdpgfxMapSurfaceToWindow)(RdpgfxServerContext* context, RDPGFX_MAP_SURFACE_TO_WINDOW_PDU* surfaceToWindow);
|
||||
typedef UINT(*psRdpgfxCapsAdvertise)(RdpgfxServerContext* context, RDPGFX_CAPS_ADVERTISE_PDU* capsAdvertise);
|
||||
typedef UINT(*psRdpgfxCapsConfirm)(RdpgfxServerContext* context, RDPGFX_CAPS_CONFIRM_PDU* capsConfirm);
|
||||
typedef UINT(*psRdpgfxFrameAcknowledge)(RdpgfxServerContext* context, RDPGFX_FRAME_ACKNOWLEDGE_PDU* frameAcknowledge);
|
||||
typedef UINT(*psRdpgfxQoeFrameAcknowledge)(RdpgfxServerContext* context, RDPGFX_QOE_FRAME_ACKNOWLEDGE_PDU* qoeFrameAcknowledge);
|
||||
|
||||
struct _rdpgfx_server_context
|
||||
{
|
||||
HANDLE vcm;
|
||||
void* custom;
|
||||
|
||||
psRdpgfxServerOpen Open;
|
||||
psRdpgfxServerClose Close;
|
||||
|
||||
psRdpgfxResetGraphics ResetGraphics;
|
||||
psRdpgfxStartFrame StartFrame;
|
||||
psRdpgfxEndFrame EndFrame;
|
||||
psRdpgfxSurfaceCommand SurfaceCommand;
|
||||
psRdpgfxSurfaceFrameCommand SurfaceFrameCommand;
|
||||
psRdpgfxDeleteEncodingContext DeleteEncodingContext;
|
||||
psRdpgfxCreateSurface CreateSurface;
|
||||
psRdpgfxDeleteSurface DeleteSurface;
|
||||
psRdpgfxSolidFill SolidFill;
|
||||
psRdpgfxSurfaceToSurface SurfaceToSurface;
|
||||
psRdpgfxSurfaceToCache SurfaceToCache;
|
||||
psRdpgfxCacheToSurface CacheToSurface;
|
||||
psRdpgfxCacheImportOffer CacheImportOffer;
|
||||
psRdpgfxCacheImportReply CacheImportReply;
|
||||
psRdpgfxEvictCacheEntry EvictCacheEntry;
|
||||
psRdpgfxMapSurfaceToOutput MapSurfaceToOutput;
|
||||
psRdpgfxMapSurfaceToWindow MapSurfaceToWindow;
|
||||
psRdpgfxCapsAdvertise CapsAdvertise;
|
||||
psRdpgfxCapsConfirm CapsConfirm;
|
||||
psRdpgfxFrameAcknowledge FrameAcknowledge;
|
||||
psRdpgfxQoeFrameAcknowledge QoeFrameAcknowledge;
|
||||
|
||||
RdpgfxServerPrivate* priv;
|
||||
rdpContext* rdpcontext;
|
||||
};
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
FREERDP_API RdpgfxServerContext* rdpgfx_server_context_new(HANDLE vcm);
|
||||
FREERDP_API void rdpgfx_server_context_free(RdpgfxServerContext* context);
|
||||
FREERDP_API HANDLE rdpgfx_server_get_event_handle(RdpgfxServerContext* context);
|
||||
FREERDP_API UINT rdpgfx_server_handle_messages(RdpgfxServerContext* context);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif /* FREERDP_CHANNEL_SERVER_RDPGFX_H */
|
@ -33,6 +33,7 @@
|
||||
#include <freerdp/server/remdesk.h>
|
||||
#include <freerdp/server/rdpsnd.h>
|
||||
#include <freerdp/server/audin.h>
|
||||
#include <freerdp/server/rdpgfx.h>
|
||||
|
||||
#include <freerdp/codec/color.h>
|
||||
#include <freerdp/codec/region.h>
|
||||
@ -87,6 +88,7 @@ struct rdp_shadow_client
|
||||
BOOL inLobby;
|
||||
BOOL mayView;
|
||||
BOOL mayInteract;
|
||||
BOOL suppressOutput;
|
||||
wMessageQueue* MsgQueue;
|
||||
CRITICAL_SECTION lock;
|
||||
REGION16 invalidRegion;
|
||||
@ -102,6 +104,7 @@ struct rdp_shadow_client
|
||||
RemdeskServerContext* remdesk;
|
||||
RdpsndServerContext* rdpsnd;
|
||||
audin_server_context* audin;
|
||||
RdpgfxServerContext* rdpgfx;
|
||||
};
|
||||
|
||||
struct rdp_shadow_server
|
||||
@ -124,6 +127,14 @@ struct rdp_shadow_server
|
||||
BOOL authentication;
|
||||
int selectedMonitor;
|
||||
RECTANGLE_16 subRect;
|
||||
|
||||
/* Codec settings */
|
||||
RLGR_MODE rfxMode;
|
||||
H264_RATECONTROL_MODE h264RateControlMode;
|
||||
UINT32 h264BitRate;
|
||||
FLOAT h264FrameRate;
|
||||
UINT32 h264QP;
|
||||
|
||||
char* ipcSocket;
|
||||
char* ConfigPath;
|
||||
char* CertificateFile;
|
||||
@ -169,9 +180,12 @@ struct _RDP_SHADOW_ENTRY_POINTS
|
||||
int selectedMonitor; \
|
||||
MONITOR_DEF monitors[16]; \
|
||||
MONITOR_DEF virtualScreen; \
|
||||
\
|
||||
/* This event indicates that we have graphic change */ \
|
||||
/* such as screen update and resize. It should not be */ \
|
||||
/* used by subsystem implementation directly */ \
|
||||
rdpShadowMultiClientEvent* updateEvent; \
|
||||
BOOL suppressOutput; \
|
||||
REGION16 invalidRegion; \
|
||||
\
|
||||
wMessagePipe* MsgPipe; \
|
||||
UINT32 pointerX; \
|
||||
UINT32 pointerY; \
|
||||
@ -201,22 +215,7 @@ struct rdp_shadow_subsystem
|
||||
};
|
||||
|
||||
/* Definition of message between subsystem and clients */
|
||||
#define SHADOW_MSG_IN_REFRESH_OUTPUT_ID 1001
|
||||
#define SHADOW_MSG_IN_SUPPRESS_OUTPUT_ID 1002
|
||||
|
||||
struct _SHADOW_MSG_IN_REFRESH_OUTPUT
|
||||
{
|
||||
UINT32 numRects;
|
||||
RECTANGLE_16* rects;
|
||||
};
|
||||
typedef struct _SHADOW_MSG_IN_REFRESH_OUTPUT SHADOW_MSG_IN_REFRESH_OUTPUT;
|
||||
|
||||
struct _SHADOW_MSG_IN_SUPPRESS_OUTPUT
|
||||
{
|
||||
BOOL allow;
|
||||
RECTANGLE_16 rect;
|
||||
};
|
||||
typedef struct _SHADOW_MSG_IN_SUPPRESS_OUTPUT SHADOW_MSG_IN_SUPPRESS_OUTPUT;
|
||||
#define SHADOW_MSG_IN_REFRESH_REQUEST_ID 1001
|
||||
|
||||
typedef struct _SHADOW_MSG_OUT SHADOW_MSG_OUT;
|
||||
typedef void (*MSG_OUT_FREE_FN)(UINT32 id, SHADOW_MSG_OUT* msg); /* function to free SHADOW_MSG_OUT */
|
||||
|
@ -1,10 +1,217 @@
|
||||
#include <winpr/crt.h>
|
||||
#include <winpr/print.h>
|
||||
#include <winpr/bitstream.h>
|
||||
|
||||
#include <freerdp/freerdp.h>
|
||||
#include <freerdp/codec/zgfx.h>
|
||||
#include <freerdp/log.h>
|
||||
|
||||
int TestFreeRDPCodecZGfx(int argc, char* argv[])
|
||||
/* Sample from [MS-RDPEGFX] */
|
||||
static const BYTE TEST_FOX_DATA[] =
|
||||
"The quick brown "
|
||||
"fox jumps over t"
|
||||
"he lazy dog";
|
||||
|
||||
static const BYTE TEST_FOX_DATA_SINGLE[] =
|
||||
"\xE0\x04\x54\x68\x65\x20\x71\x75\x69\x63\x6B\x20\x62\x72\x6F\x77"
|
||||
"\x6E\x20\x66\x6F\x78\x20\x6A\x75\x6D\x70\x73\x20\x6F\x76\x65\x72"
|
||||
"\x20\x74\x68\x65\x20\x6C\x61\x7A\x79\x20\x64\x6F\x67";
|
||||
|
||||
static const BYTE TEST_FOX_DATA_MULTIPART[] =
|
||||
"\xE1\x03\x00\x2B\x00\x00\x00\x11\x00\x00\x00\x04\x54\x68\x65\x20"
|
||||
"\x71\x75\x69\x63\x6B\x20\x62\x72\x6F\x77\x6E\x20\x0E\x00\x00\x00"
|
||||
"\x04\x66\x6F\x78\x20\x6A\x75\x6D\x70\x73\x20\x6F\x76\x65\x10\x00"
|
||||
"\x00\x00\x24\x39\x08\x0E\x91\xF8\xD8\x61\x3D\x1E\x44\x06\x43\x79"
|
||||
"\x9C\x02";
|
||||
|
||||
int test_ZGfxCompressFox()
|
||||
{
|
||||
int status;
|
||||
UINT32 Flags;
|
||||
BYTE* pSrcData;
|
||||
UINT32 SrcSize;
|
||||
UINT32 DstSize;
|
||||
BYTE* pDstData;
|
||||
ZGFX_CONTEXT* zgfx;
|
||||
UINT32 expectedSize;
|
||||
|
||||
zgfx = zgfx_context_new(TRUE);
|
||||
SrcSize = sizeof(TEST_FOX_DATA) - 1;
|
||||
pSrcData = (BYTE*) TEST_FOX_DATA;
|
||||
Flags = 0;
|
||||
expectedSize = sizeof(TEST_FOX_DATA_SINGLE) - 1;
|
||||
status = zgfx_compress(zgfx, pSrcData, SrcSize, &pDstData, &DstSize, &Flags);
|
||||
printf("flags: 0x%04X size: %d\n", Flags, DstSize);
|
||||
|
||||
if (DstSize != expectedSize)
|
||||
{
|
||||
printf("test_ZGfxCompressFox: output size mismatch: Actual: %d, Expected: %d\n", DstSize, expectedSize);
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (memcmp(pDstData, TEST_FOX_DATA_SINGLE, DstSize) != 0)
|
||||
{
|
||||
printf("test_ZGfxCompressFox: output mismatch\n");
|
||||
printf("Actual\n");
|
||||
BitDump(__FUNCTION__, WLOG_INFO, pDstData, DstSize * 8, 0);
|
||||
printf("Expected\n");
|
||||
BitDump(__FUNCTION__, WLOG_INFO, TEST_FOX_DATA_SINGLE, DstSize * 8, 0);
|
||||
return -1;
|
||||
}
|
||||
|
||||
zgfx_context_free(zgfx);
|
||||
return 0;
|
||||
}
|
||||
|
||||
int test_ZGfxDecompressFoxSingle()
|
||||
{
|
||||
int status;
|
||||
UINT32 Flags;
|
||||
BYTE* pSrcData;
|
||||
UINT32 SrcSize;
|
||||
UINT32 DstSize;
|
||||
BYTE* pDstData;
|
||||
ZGFX_CONTEXT* zgfx;
|
||||
UINT32 expectedSize;
|
||||
|
||||
zgfx = zgfx_context_new(TRUE);
|
||||
SrcSize = sizeof(TEST_FOX_DATA_SINGLE) - 1;
|
||||
pSrcData = (BYTE*) TEST_FOX_DATA_SINGLE;
|
||||
Flags = 0;
|
||||
expectedSize = sizeof(TEST_FOX_DATA) - 1;
|
||||
status = zgfx_decompress(zgfx, pSrcData, SrcSize, &pDstData, &DstSize, Flags);
|
||||
printf("flags: 0x%04X size: %d\n", Flags, DstSize);
|
||||
|
||||
if (DstSize != expectedSize)
|
||||
{
|
||||
printf("test_ZGfxDecompressFoxSingle: output size mismatch: Actual: %d, Expected: %d\n", DstSize, expectedSize);
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (memcmp(pDstData, TEST_FOX_DATA, DstSize) != 0)
|
||||
{
|
||||
printf("test_ZGfxDecompressFoxSingle: output mismatch\n");
|
||||
printf("Actual\n");
|
||||
BitDump(__FUNCTION__, WLOG_INFO, pDstData, DstSize * 8, 0);
|
||||
printf("Expected\n");
|
||||
BitDump(__FUNCTION__, WLOG_INFO, TEST_FOX_DATA, DstSize * 8, 0);
|
||||
return -1;
|
||||
}
|
||||
|
||||
zgfx_context_free(zgfx);
|
||||
return 0;
|
||||
}
|
||||
|
||||
int test_ZGfxDecompressFoxMultipart()
|
||||
{
|
||||
int status;
|
||||
UINT32 Flags;
|
||||
BYTE* pSrcData;
|
||||
UINT32 SrcSize;
|
||||
UINT32 DstSize;
|
||||
BYTE* pDstData;
|
||||
ZGFX_CONTEXT* zgfx;
|
||||
UINT32 expectedSize;
|
||||
|
||||
zgfx = zgfx_context_new(TRUE);
|
||||
SrcSize = sizeof(TEST_FOX_DATA_MULTIPART) - 1;
|
||||
pSrcData = (BYTE*) TEST_FOX_DATA_MULTIPART;
|
||||
Flags = 0;
|
||||
expectedSize = sizeof(TEST_FOX_DATA) - 1;
|
||||
status = zgfx_decompress(zgfx, pSrcData, SrcSize, &pDstData, &DstSize, Flags);
|
||||
printf("flags: 0x%04X size: %d\n", Flags, DstSize);
|
||||
|
||||
if (DstSize != expectedSize)
|
||||
{
|
||||
printf("test_ZGfxDecompressFoxSingle: output size mismatch: Actual: %d, Expected: %d\n", DstSize, expectedSize);
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (memcmp(pDstData, TEST_FOX_DATA, DstSize) != 0)
|
||||
{
|
||||
printf("test_ZGfxDecompressFoxSingle: output mismatch\n");
|
||||
printf("Actual\n");
|
||||
BitDump(__FUNCTION__, WLOG_INFO, pDstData, DstSize * 8, 0);
|
||||
printf("Expected\n");
|
||||
BitDump(__FUNCTION__, WLOG_INFO, TEST_FOX_DATA, DstSize * 8, 0);
|
||||
return -1;
|
||||
}
|
||||
|
||||
zgfx_context_free(zgfx);
|
||||
return 0;
|
||||
}
|
||||
|
||||
int test_ZGfxCompressConsistent()
|
||||
{
|
||||
int status;
|
||||
UINT32 Flags;
|
||||
BYTE* pSrcData;
|
||||
UINT32 SrcSize;
|
||||
UINT32 DstSize;
|
||||
BYTE* pDstData;
|
||||
UINT32 DstSize2;
|
||||
BYTE* pDstData2;
|
||||
ZGFX_CONTEXT* zgfx;
|
||||
UINT32 expectedSize;
|
||||
BYTE BigBuffer[65536];
|
||||
|
||||
memset(BigBuffer, 0xaa, sizeof(BigBuffer));
|
||||
memcpy(BigBuffer, TEST_FOX_DATA, sizeof(TEST_FOX_DATA) - 1);
|
||||
zgfx = zgfx_context_new(TRUE);
|
||||
|
||||
/* Compress */
|
||||
expectedSize = SrcSize = sizeof(BigBuffer);
|
||||
pSrcData = (BYTE*) BigBuffer;
|
||||
Flags = 0;
|
||||
status = zgfx_compress(zgfx, pSrcData, SrcSize, &pDstData2, &DstSize2, &Flags);
|
||||
printf("Compress: flags: 0x%04X size: %d\n", Flags, DstSize2);
|
||||
|
||||
/* Decompress */
|
||||
status = zgfx_decompress(zgfx, pDstData2, DstSize2, &pDstData, &DstSize, Flags);
|
||||
printf("Decompress: flags: 0x%04X size: %d\n", Flags, DstSize);
|
||||
|
||||
if (DstSize != expectedSize)
|
||||
{
|
||||
printf("test_ZGfxDecompressFoxSingle: output size mismatch: Actual: %d, Expected: %d\n", DstSize, expectedSize);
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (memcmp(pDstData, BigBuffer, DstSize) != 0)
|
||||
{
|
||||
printf("test_ZGfxDecompressFoxSingle: output mismatch\n");
|
||||
printf("Actual\n");
|
||||
BitDump(__FUNCTION__, WLOG_INFO, pDstData, 64 * 8, 0);
|
||||
printf("...\n");
|
||||
BitDump(__FUNCTION__, WLOG_INFO, pDstData + DstSize - 64, 64 * 8, 0);
|
||||
printf("Expected\n");
|
||||
BitDump(__FUNCTION__, WLOG_INFO, BigBuffer, 64 * 8, 0);
|
||||
printf("...\n");
|
||||
BitDump(__FUNCTION__, WLOG_INFO, BigBuffer + DstSize - 64, 64 * 8, 0);
|
||||
printf("Middle Result\n");
|
||||
BitDump(__FUNCTION__, WLOG_INFO, pDstData2, 64 * 8, 0);
|
||||
printf("...\n");
|
||||
BitDump(__FUNCTION__, WLOG_INFO, pDstData2 + DstSize2 - 64, 64 * 8, 0);
|
||||
return -1;
|
||||
}
|
||||
|
||||
zgfx_context_free(zgfx);
|
||||
return 0;
|
||||
}
|
||||
|
||||
int TestFreeRDPCodecZGfx(int argc, char* argv[])
|
||||
{
|
||||
if (test_ZGfxCompressFox() < 0)
|
||||
return -1;
|
||||
|
||||
if (test_ZGfxDecompressFoxSingle() < 0)
|
||||
return -1;
|
||||
|
||||
if (test_ZGfxDecompressFoxMultipart() < 0)
|
||||
return -1;
|
||||
|
||||
if (test_ZGfxCompressConsistent() < 0)
|
||||
return -1;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
@ -25,8 +25,11 @@
|
||||
#include <winpr/print.h>
|
||||
#include <winpr/bitstream.h>
|
||||
|
||||
#include <freerdp/log.h>
|
||||
#include <freerdp/codec/zgfx.h>
|
||||
|
||||
#define TAG FREERDP_TAG("codec")
|
||||
|
||||
/**
|
||||
* RDP8 Compressor Limits:
|
||||
*
|
||||
@ -105,7 +108,7 @@ static const ZGFX_TOKEN ZGFX_TOKEN_TABLE[] =
|
||||
_zgfx->bits = _zgfx->BitsCurrent >> _zgfx->cBitsCurrent; \
|
||||
_zgfx->BitsCurrent &= ((1 << _zgfx->cBitsCurrent) - 1);
|
||||
|
||||
void zgfx_history_buffer_ring_write(ZGFX_CONTEXT* zgfx, BYTE* src, UINT32 count)
|
||||
void zgfx_history_buffer_ring_write(ZGFX_CONTEXT* zgfx, const BYTE* src, UINT32 count)
|
||||
{
|
||||
UINT32 front;
|
||||
UINT32 residue;
|
||||
@ -188,7 +191,7 @@ void zgfx_history_buffer_ring_read(ZGFX_CONTEXT* zgfx, int offset, BYTE* dst, UI
|
||||
while ((bytesLeft -= bytes) > 0);
|
||||
}
|
||||
|
||||
int zgfx_decompress_segment(ZGFX_CONTEXT* zgfx, BYTE* pbSegment, UINT32 cbSegment)
|
||||
static int zgfx_decompress_segment(ZGFX_CONTEXT* zgfx, const BYTE* pbSegment, UINT32 cbSegment)
|
||||
{
|
||||
BYTE c;
|
||||
BYTE flags;
|
||||
@ -322,7 +325,7 @@ int zgfx_decompress_segment(ZGFX_CONTEXT* zgfx, BYTE* pbSegment, UINT32 cbSegmen
|
||||
return 1;
|
||||
}
|
||||
|
||||
int zgfx_decompress(ZGFX_CONTEXT* zgfx, BYTE* pSrcData, UINT32 SrcSize, BYTE** ppDstData, UINT32* pDstSize, UINT32 flags)
|
||||
int zgfx_decompress(ZGFX_CONTEXT* zgfx, const BYTE* pSrcData, UINT32 SrcSize, BYTE** ppDstData, UINT32* pDstSize, UINT32 flags)
|
||||
{
|
||||
int status;
|
||||
BYTE descriptor;
|
||||
@ -383,11 +386,120 @@ int zgfx_decompress(ZGFX_CONTEXT* zgfx, BYTE* pSrcData, UINT32 SrcSize, BYTE** p
|
||||
return 1;
|
||||
}
|
||||
|
||||
int zgfx_compress(ZGFX_CONTEXT* zgfx, BYTE* pSrcData, UINT32 SrcSize, BYTE** ppDstData, UINT32* pDstSize, UINT32* pFlags)
|
||||
static int zgfx_compress_segment(ZGFX_CONTEXT* zgfx, wStream* s, const BYTE* pSrcData, UINT32 SrcSize, UINT32* pFlags)
|
||||
{
|
||||
/* FIXME: Currently compression not implemented. Just copy the raw source */
|
||||
|
||||
if (!Stream_EnsureRemainingCapacity(s, SrcSize + 1))
|
||||
{
|
||||
WLog_ERR(TAG, "Stream_EnsureRemainingCapacity failed!");
|
||||
return -1;
|
||||
}
|
||||
(*pFlags) |= ZGFX_PACKET_COMPR_TYPE_RDP8; /* RDP 8.0 compression format */
|
||||
Stream_Write_UINT8(s, (*pFlags)); /* header (1 byte) */
|
||||
Stream_Write(s, pSrcData, SrcSize);
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
int zgfx_compress_to_stream(ZGFX_CONTEXT* zgfx, wStream* sDst, const BYTE* pUncompressed, UINT32 uncompressedSize, UINT32* pFlags)
|
||||
{
|
||||
int fragment;
|
||||
UINT16 maxLength;
|
||||
UINT32 totalLength;
|
||||
size_t posSegmentCount = 0;
|
||||
const BYTE* pSrcData;
|
||||
int status = 0;
|
||||
|
||||
maxLength = ZGFX_SEGMENTED_MAXSIZE;
|
||||
|
||||
totalLength = uncompressedSize;
|
||||
pSrcData = pUncompressed;
|
||||
for (fragment = 0; (totalLength > 0) || (fragment == 0); fragment++)
|
||||
{
|
||||
UINT32 SrcSize;
|
||||
size_t posDstSize;
|
||||
size_t posDataStart;
|
||||
UINT32 DstSize;
|
||||
|
||||
SrcSize = (totalLength > maxLength) ? maxLength : totalLength;
|
||||
posDstSize = 0;
|
||||
totalLength -= SrcSize;
|
||||
|
||||
/* Ensure we have enough space for headers */
|
||||
if (!Stream_EnsureRemainingCapacity(sDst, 12))
|
||||
{
|
||||
WLog_ERR(TAG, "Stream_EnsureRemainingCapacity failed!");
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (fragment == 0)
|
||||
{
|
||||
/* First fragment */
|
||||
|
||||
/* descriptor (1 byte) */
|
||||
Stream_Write_UINT8(sDst, (totalLength == 0) ?
|
||||
ZGFX_SEGMENTED_SINGLE : ZGFX_SEGMENTED_MULTIPART);
|
||||
if (totalLength > 0)
|
||||
{
|
||||
posSegmentCount = Stream_GetPosition(sDst); /* segmentCount (2 bytes) */
|
||||
Stream_Seek(sDst, 2);
|
||||
Stream_Write_UINT32(sDst, uncompressedSize); /* uncompressedSize (4 bytes) */
|
||||
}
|
||||
}
|
||||
|
||||
if (fragment > 0 || totalLength > 0)
|
||||
{
|
||||
/* Multipart */
|
||||
posDstSize = Stream_GetPosition(sDst); /* size (4 bytes) */
|
||||
Stream_Seek(sDst, 4);
|
||||
}
|
||||
|
||||
posDataStart = Stream_GetPosition(sDst);
|
||||
if ((status = zgfx_compress_segment(zgfx, sDst, pSrcData, SrcSize, pFlags)) < 0)
|
||||
{
|
||||
return status;
|
||||
}
|
||||
|
||||
if (posDstSize)
|
||||
{
|
||||
/* Fill segment data size */
|
||||
DstSize = Stream_GetPosition(sDst) - posDataStart;
|
||||
Stream_SetPosition(sDst, posDstSize);
|
||||
Stream_Write_UINT32(sDst, DstSize);
|
||||
Stream_SetPosition(sDst, posDataStart + DstSize);
|
||||
}
|
||||
|
||||
pSrcData += SrcSize;
|
||||
}
|
||||
|
||||
Stream_SealLength(sDst);
|
||||
|
||||
/* fill back segmentCount */
|
||||
if (posSegmentCount)
|
||||
{
|
||||
Stream_SetPosition(sDst, posSegmentCount);
|
||||
Stream_Write_UINT16(sDst, fragment);
|
||||
Stream_SetPosition(sDst, Stream_Length(sDst));
|
||||
}
|
||||
|
||||
return status;
|
||||
}
|
||||
|
||||
int zgfx_compress(ZGFX_CONTEXT* zgfx, const BYTE* pSrcData, UINT32 SrcSize, BYTE** ppDstData, UINT32* pDstSize, UINT32* pFlags)
|
||||
{
|
||||
int status;
|
||||
wStream* s = Stream_New(NULL, SrcSize);
|
||||
|
||||
status = zgfx_compress_to_stream(zgfx, s, pSrcData, SrcSize, pFlags);
|
||||
(*ppDstData) = Stream_Buffer(s);
|
||||
(*pDstSize) = Stream_GetPosition(s);
|
||||
|
||||
Stream_Free(s, FALSE);
|
||||
return status;
|
||||
}
|
||||
|
||||
|
||||
void zgfx_context_reset(ZGFX_CONTEXT* zgfx, BOOL flush)
|
||||
{
|
||||
zgfx->HistoryIndex = 0;
|
||||
|
@ -557,6 +557,13 @@ BOOL WTSVirtualChannelManagerIsChannelJoined(HANDLE hServer, const char* name)
|
||||
return wts_get_joined_channel_by_name(vcm->rdp->mcs, name) == NULL ? FALSE : TRUE;
|
||||
}
|
||||
|
||||
BYTE WTSVirtualChannelManagerGetDrdynvcState(HANDLE hServer)
|
||||
{
|
||||
WTSVirtualChannelManager* vcm = (WTSVirtualChannelManager*) hServer;
|
||||
|
||||
return vcm->drdynvc_state;
|
||||
}
|
||||
|
||||
UINT16 WTSChannelGetId(freerdp_peer* client, const char* channel_name)
|
||||
{
|
||||
rdpMcsChannel* channel;
|
||||
@ -1205,6 +1212,7 @@ BOOL WINAPI FreeRDP_WTSVirtualChannelWrite(HANDLE hChannelHandle, PCHAR Buffer,
|
||||
BYTE* buffer;
|
||||
UINT32 length;
|
||||
UINT32 written;
|
||||
UINT32 totalWritten = 0;
|
||||
rdpPeerChannel* channel = (rdpPeerChannel*) hChannelHandle;
|
||||
BOOL ret = TRUE;
|
||||
|
||||
@ -1222,6 +1230,8 @@ BOOL WINAPI FreeRDP_WTSVirtualChannelWrite(HANDLE hChannelHandle, PCHAR Buffer,
|
||||
}
|
||||
CopyMemory(buffer, Buffer, length);
|
||||
|
||||
totalWritten = Length;
|
||||
|
||||
ret = wts_queue_send_item(channel, buffer, length);
|
||||
}
|
||||
else if (!channel->vcm->drdynvc_channel || (channel->vcm->drdynvc_state != DRDYNVC_STATE_READY))
|
||||
@ -1270,13 +1280,14 @@ BOOL WINAPI FreeRDP_WTSVirtualChannelWrite(HANDLE hChannelHandle, PCHAR Buffer,
|
||||
|
||||
Length -= written;
|
||||
Buffer += written;
|
||||
totalWritten += written;
|
||||
|
||||
ret = wts_queue_send_item(channel->vcm->drdynvc_channel, buffer, length);
|
||||
}
|
||||
}
|
||||
|
||||
if (pBytesWritten)
|
||||
*pBytesWritten = Length;
|
||||
*pBytesWritten = totalWritten;
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
@ -47,13 +47,6 @@ enum
|
||||
RDP_PEER_CHANNEL_TYPE_DVC = 1
|
||||
};
|
||||
|
||||
enum
|
||||
{
|
||||
DRDYNVC_STATE_NONE = 0,
|
||||
DRDYNVC_STATE_INITIALIZED = 1,
|
||||
DRDYNVC_STATE_READY = 2
|
||||
};
|
||||
|
||||
enum
|
||||
{
|
||||
DVC_OPEN_STATE_NONE = 0,
|
||||
|
@ -45,6 +45,8 @@ set(${MODULE_PREFIX}_SRCS
|
||||
shadow_rdpsnd.h
|
||||
shadow_audin.c
|
||||
shadow_audin.h
|
||||
shadow_rdpgfx.c
|
||||
shadow_rdpgfx.h
|
||||
shadow_subsystem.c
|
||||
shadow_subsystem.h
|
||||
shadow_mcevent.c
|
||||
|
@ -268,6 +268,7 @@ int mac_shadow_capture_get_dirty_region(macShadowSubsystem* subsystem)
|
||||
size_t numRects;
|
||||
const CGRect* rects;
|
||||
RECTANGLE_16 invalidRect;
|
||||
rdpShadowSurface* surface = subsystem->server->surface;
|
||||
|
||||
rects = CGDisplayStreamUpdateGetRects(subsystem->lastUpdate, kCGDisplayStreamUpdateDirtyRects, &numRects);
|
||||
|
||||
@ -290,7 +291,7 @@ int mac_shadow_capture_get_dirty_region(macShadowSubsystem* subsystem)
|
||||
invalidRect.bottom /= 2;
|
||||
}
|
||||
|
||||
region16_union_rect(&(subsystem->invalidRegion), &(subsystem->invalidRegion), &invalidRect);
|
||||
region16_union_rect(&(surface->invalidRegion), &(surface->invalidRegion), &invalidRect);
|
||||
}
|
||||
|
||||
return 0;
|
||||
@ -316,9 +317,6 @@ void (^mac_capture_stream_handler)(CGDisplayStreamFrameStatus, uint64_t, IOSurfa
|
||||
if (count < 1)
|
||||
return;
|
||||
|
||||
if ((count == 1) && subsystem->suppressOutput)
|
||||
return;
|
||||
|
||||
mac_shadow_capture_get_dirty_region(subsystem);
|
||||
|
||||
surfaceRect.left = 0;
|
||||
@ -326,11 +324,11 @@ void (^mac_capture_stream_handler)(CGDisplayStreamFrameStatus, uint64_t, IOSurfa
|
||||
surfaceRect.right = surface->width;
|
||||
surfaceRect.bottom = surface->height;
|
||||
|
||||
region16_intersect_rect(&(subsystem->invalidRegion), &(subsystem->invalidRegion), &surfaceRect);
|
||||
region16_intersect_rect(&(surface->invalidRegion), &(surface->invalidRegion), &surfaceRect);
|
||||
|
||||
if (!region16_is_empty(&(subsystem->invalidRegion)))
|
||||
if (!region16_is_empty(&(surface->invalidRegion)))
|
||||
{
|
||||
extents = region16_extents(&(subsystem->invalidRegion));
|
||||
extents = region16_extents(&(surface->invalidRegion));
|
||||
|
||||
x = extents->left;
|
||||
y = extents->top;
|
||||
@ -359,7 +357,9 @@ void (^mac_capture_stream_handler)(CGDisplayStreamFrameStatus, uint64_t, IOSurfa
|
||||
|
||||
count = ArrayList_Count(server->clients);
|
||||
|
||||
EnterCriticalSection(&(surface->lock));
|
||||
shadow_subsystem_frame_update((rdpShadowSubsystem *)subsystem);
|
||||
LeaveCriticalSection(&(surface->lock));
|
||||
|
||||
if (count == 1)
|
||||
{
|
||||
@ -375,7 +375,7 @@ void (^mac_capture_stream_handler)(CGDisplayStreamFrameStatus, uint64_t, IOSurfa
|
||||
|
||||
ArrayList_Unlock(server->clients);
|
||||
|
||||
region16_clear(&(subsystem->invalidRegion));
|
||||
region16_clear(&(surface->invalidRegion));
|
||||
}
|
||||
|
||||
if (status != kCGDisplayStreamFrameStatusFrameComplete)
|
||||
@ -444,48 +444,15 @@ int mac_shadow_screen_grab(macShadowSubsystem* subsystem)
|
||||
|
||||
int mac_shadow_subsystem_process_message(macShadowSubsystem* subsystem, wMessage* message)
|
||||
{
|
||||
rdpShadowServer* server = subsystem->server;
|
||||
rdpShadowSurface* surface = server->surface;
|
||||
switch(message->id)
|
||||
{
|
||||
case SHADOW_MSG_IN_REFRESH_OUTPUT_ID:
|
||||
{
|
||||
UINT32 index;
|
||||
SHADOW_MSG_IN_REFRESH_OUTPUT* msg = (SHADOW_MSG_IN_REFRESH_OUTPUT*) message->wParam;
|
||||
|
||||
if (msg->numRects)
|
||||
{
|
||||
for (index = 0; index < msg->numRects; index++)
|
||||
{
|
||||
region16_union_rect(&(subsystem->invalidRegion),
|
||||
&(subsystem->invalidRegion), &msg->rects[index]);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
RECTANGLE_16 refreshRect;
|
||||
|
||||
refreshRect.left = 0;
|
||||
refreshRect.top = 0;
|
||||
refreshRect.right = subsystem->width;
|
||||
refreshRect.bottom = subsystem->height;
|
||||
|
||||
region16_union_rect(&(subsystem->invalidRegion),
|
||||
&(subsystem->invalidRegion), &refreshRect);
|
||||
}
|
||||
case SHADOW_MSG_IN_REFRESH_REQUEST_ID:
|
||||
EnterCriticalSection(&(surface->lock));
|
||||
shadow_subsystem_frame_update((rdpShadowSubsystem *)subsystem);
|
||||
LeaveCriticalSection(&(surface->lock));
|
||||
break;
|
||||
}
|
||||
case SHADOW_MSG_IN_SUPPRESS_OUTPUT_ID:
|
||||
{
|
||||
SHADOW_MSG_IN_SUPPRESS_OUTPUT* msg = (SHADOW_MSG_IN_SUPPRESS_OUTPUT*) message->wParam;
|
||||
|
||||
subsystem->suppressOutput = (msg->allow) ? FALSE : TRUE;
|
||||
|
||||
if (msg->allow)
|
||||
{
|
||||
region16_union_rect(&(subsystem->invalidRegion),
|
||||
&(subsystem->invalidRegion), &(msg->rect));
|
||||
}
|
||||
break;
|
||||
}
|
||||
default:
|
||||
WLog_ERR(TAG, "Unknown message id: %u", message->id);
|
||||
break;
|
||||
|
@ -638,6 +638,7 @@ int win_shadow_dxgi_get_invalid_region(winShadowSubsystem* subsystem)
|
||||
RECT* pDirtyRectsBuffer;
|
||||
DXGI_OUTDUPL_MOVE_RECT* pMoveRect;
|
||||
DXGI_OUTDUPL_MOVE_RECT* pMoveRectBuffer;
|
||||
rdpShadowSurface* surface = subsystem->server->surface;
|
||||
|
||||
if (subsystem->dxgiFrameInfo.AccumulatedFrames == 0)
|
||||
return 0;
|
||||
@ -704,7 +705,7 @@ int win_shadow_dxgi_get_invalid_region(winShadowSubsystem* subsystem)
|
||||
invalidRect.right = (UINT16) pDstRect->right;
|
||||
invalidRect.bottom = (UINT16) pDstRect->bottom;
|
||||
|
||||
region16_union_rect(&(subsystem->invalidRegion), &(subsystem->invalidRegion), &invalidRect);
|
||||
region16_union_rect(&(surface->invalidRegion), &(surface->invalidRegion), &invalidRect);
|
||||
}
|
||||
|
||||
numDirtyRects = DirtyRectsBufferSize / sizeof(RECT);
|
||||
@ -718,7 +719,7 @@ int win_shadow_dxgi_get_invalid_region(winShadowSubsystem* subsystem)
|
||||
invalidRect.right = (UINT16) pDirtyRect->right;
|
||||
invalidRect.bottom = (UINT16) pDirtyRect->bottom;
|
||||
|
||||
region16_union_rect(&(subsystem->invalidRegion), &(subsystem->invalidRegion), &invalidRect);
|
||||
region16_union_rect(&(surface->invalidRegion), &(surface->invalidRegion), &invalidRect);
|
||||
}
|
||||
|
||||
return 1;
|
||||
|
@ -63,6 +63,7 @@ BOOL shw_end_paint(rdpContext* context)
|
||||
rdpGdi* gdi = context->gdi;
|
||||
shwContext* shw = (shwContext*) context;
|
||||
winShadowSubsystem* subsystem = shw->subsystem;
|
||||
rdpShadowSurface* surface = subsystem->server->surface;
|
||||
|
||||
ninvalid = gdi->primary->hdc->hwnd->ninvalid;
|
||||
cinvalid = gdi->primary->hdc->hwnd->cinvalid;
|
||||
@ -74,7 +75,7 @@ BOOL shw_end_paint(rdpContext* context)
|
||||
invalidRect.right = cinvalid[index].x + cinvalid[index].w;
|
||||
invalidRect.bottom = cinvalid[index].y + cinvalid[index].h;
|
||||
|
||||
region16_union_rect(&(subsystem->invalidRegion), &(subsystem->invalidRegion), &invalidRect);
|
||||
region16_union_rect(&(surface->invalidRegion), &(surface->invalidRegion), &invalidRect);
|
||||
}
|
||||
|
||||
SetEvent(subsystem->RdpUpdateEnterEvent);
|
||||
|
@ -219,7 +219,7 @@ int win_shadow_surface_copy(winShadowSubsystem* subsystem)
|
||||
|
||||
if (ArrayList_Count(server->clients) < 1)
|
||||
{
|
||||
region16_clear(&(subsystem->invalidRegion));
|
||||
region16_clear(&(surface->invalidRegion));
|
||||
return 1;
|
||||
}
|
||||
|
||||
@ -228,12 +228,12 @@ int win_shadow_surface_copy(winShadowSubsystem* subsystem)
|
||||
surfaceRect.right = surface->x + surface->width;
|
||||
surfaceRect.bottom = surface->y + surface->height;
|
||||
|
||||
region16_intersect_rect(&(subsystem->invalidRegion), &(subsystem->invalidRegion), &surfaceRect);
|
||||
region16_intersect_rect(&(surface->invalidRegion), &(surface->invalidRegion), &surfaceRect);
|
||||
|
||||
if (region16_is_empty(&(subsystem->invalidRegion)))
|
||||
if (region16_is_empty(&(surface->invalidRegion)))
|
||||
return 1;
|
||||
|
||||
extents = region16_extents(&(subsystem->invalidRegion));
|
||||
extents = region16_extents(&(surface->invalidRegion));
|
||||
CopyMemory(&invalidRect, extents, sizeof(RECTANGLE_16));
|
||||
|
||||
shadow_capture_align_clip_rect(&invalidRect, &surfaceRect);
|
||||
@ -286,7 +286,7 @@ int win_shadow_surface_copy(winShadowSubsystem* subsystem)
|
||||
|
||||
ArrayList_Unlock(server->clients);
|
||||
|
||||
region16_clear(&(subsystem->invalidRegion));
|
||||
region16_clear(&(surface->invalidRegion));
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
@ -763,9 +763,6 @@ int x11_shadow_screen_grab(x11ShadowSubsystem* subsystem)
|
||||
if (count < 1)
|
||||
return 1;
|
||||
|
||||
if ((count == 1) && subsystem->suppressOutput)
|
||||
return 1;
|
||||
|
||||
surfaceRect.left = 0;
|
||||
surfaceRect.top = 0;
|
||||
surfaceRect.right = surface->width;
|
||||
@ -814,12 +811,12 @@ int x11_shadow_screen_grab(x11ShadowSubsystem* subsystem)
|
||||
|
||||
XUnlockDisplay(subsystem->display);
|
||||
|
||||
region16_union_rect(&(subsystem->invalidRegion), &(subsystem->invalidRegion), &invalidRect);
|
||||
region16_intersect_rect(&(subsystem->invalidRegion), &(subsystem->invalidRegion), &surfaceRect);
|
||||
region16_union_rect(&(surface->invalidRegion), &(surface->invalidRegion), &invalidRect);
|
||||
region16_intersect_rect(&(surface->invalidRegion), &(surface->invalidRegion), &surfaceRect);
|
||||
|
||||
if (!region16_is_empty(&(subsystem->invalidRegion)))
|
||||
if (!region16_is_empty(&(surface->invalidRegion)))
|
||||
{
|
||||
extents = region16_extents(&(subsystem->invalidRegion));
|
||||
extents = region16_extents(&(surface->invalidRegion));
|
||||
|
||||
x = extents->left;
|
||||
y = extents->top;
|
||||
@ -849,7 +846,7 @@ int x11_shadow_screen_grab(x11ShadowSubsystem* subsystem)
|
||||
}
|
||||
}
|
||||
|
||||
region16_clear(&(subsystem->invalidRegion));
|
||||
region16_clear(&(surface->invalidRegion));
|
||||
}
|
||||
|
||||
if (!subsystem->use_xshm)
|
||||
@ -868,46 +865,9 @@ int x11_shadow_subsystem_process_message(x11ShadowSubsystem* subsystem, wMessage
|
||||
{
|
||||
switch(message->id)
|
||||
{
|
||||
case SHADOW_MSG_IN_REFRESH_OUTPUT_ID:
|
||||
{
|
||||
UINT32 index;
|
||||
SHADOW_MSG_IN_REFRESH_OUTPUT* msg = (SHADOW_MSG_IN_REFRESH_OUTPUT*) message->wParam;
|
||||
|
||||
if (msg->numRects)
|
||||
{
|
||||
for (index = 0; index < msg->numRects; index++)
|
||||
{
|
||||
region16_union_rect(&(subsystem->invalidRegion),
|
||||
&(subsystem->invalidRegion), &msg->rects[index]);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
RECTANGLE_16 refreshRect;
|
||||
|
||||
refreshRect.left = 0;
|
||||
refreshRect.top = 0;
|
||||
refreshRect.right = subsystem->width;
|
||||
refreshRect.bottom = subsystem->height;
|
||||
|
||||
region16_union_rect(&(subsystem->invalidRegion),
|
||||
&(subsystem->invalidRegion), &refreshRect);
|
||||
}
|
||||
case SHADOW_MSG_IN_REFRESH_REQUEST_ID:
|
||||
shadow_subsystem_frame_update((rdpShadowSubsystem *)subsystem);
|
||||
break;
|
||||
}
|
||||
case SHADOW_MSG_IN_SUPPRESS_OUTPUT_ID:
|
||||
{
|
||||
SHADOW_MSG_IN_SUPPRESS_OUTPUT* msg = (SHADOW_MSG_IN_SUPPRESS_OUTPUT*) message->wParam;
|
||||
|
||||
subsystem->suppressOutput = (msg->allow) ? FALSE : TRUE;
|
||||
|
||||
if (msg->allow)
|
||||
{
|
||||
region16_union_rect(&(subsystem->invalidRegion),
|
||||
&(subsystem->invalidRegion), &(msg->rect));
|
||||
}
|
||||
break;
|
||||
}
|
||||
default:
|
||||
WLog_ERR(TAG, "Unknown message id: %u", message->id);
|
||||
break;
|
||||
|
@ -43,11 +43,21 @@ UINT shadow_client_channels_post_connect(rdpShadowClient* client)
|
||||
|
||||
shadow_client_audin_init(client);
|
||||
|
||||
if (client->context.settings->SupportGraphicsPipeline)
|
||||
{
|
||||
shadow_client_rdpgfx_init(client);
|
||||
}
|
||||
|
||||
return CHANNEL_RC_OK;
|
||||
}
|
||||
|
||||
void shadow_client_channels_free(rdpShadowClient* client)
|
||||
{
|
||||
if (client->context.settings->SupportGraphicsPipeline)
|
||||
{
|
||||
shadow_client_rdpgfx_uninit(client);
|
||||
}
|
||||
|
||||
shadow_client_audin_uninit(client);
|
||||
|
||||
shadow_client_rdpsnd_uninit(client);
|
||||
|
@ -28,6 +28,7 @@
|
||||
#include "shadow_remdesk.h"
|
||||
#include "shadow_rdpsnd.h"
|
||||
#include "shadow_audin.h"
|
||||
#include "shadow_rdpgfx.h"
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
|
File diff suppressed because it is too large
Load Diff
@ -25,7 +25,7 @@
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
int shadow_client_surface_update(rdpShadowClient* client, REGION16* region);
|
||||
BOOL shadow_client_surface_update(rdpShadowClient* client, REGION16* region);
|
||||
BOOL shadow_client_accepted(freerdp_listener* instance, freerdp_peer* client);
|
||||
|
||||
#ifdef __cplusplus
|
||||
|
@ -130,9 +130,6 @@ int shadow_encoder_uninit_grid(rdpShadowEncoder* encoder)
|
||||
|
||||
int shadow_encoder_init_rfx(rdpShadowEncoder* encoder)
|
||||
{
|
||||
rdpContext* context = (rdpContext*) encoder->client;
|
||||
rdpSettings* settings = context->settings;
|
||||
|
||||
if (!encoder->rfx)
|
||||
encoder->rfx = rfx_context_new(TRUE);
|
||||
|
||||
@ -142,18 +139,10 @@ int shadow_encoder_init_rfx(rdpShadowEncoder* encoder)
|
||||
if (!rfx_context_reset(encoder->rfx, encoder->width, encoder->height))
|
||||
goto fail;
|
||||
|
||||
encoder->rfx->mode = RLGR3;
|
||||
encoder->rfx->width = encoder->width;
|
||||
encoder->rfx->height = encoder->height;
|
||||
encoder->rfx->mode = encoder->server->rfxMode;
|
||||
|
||||
rfx_context_set_pixel_format(encoder->rfx, RDP_PIXEL_FORMAT_B8G8R8A8);
|
||||
|
||||
encoder->fps = 16;
|
||||
encoder->maxFps = 32;
|
||||
encoder->frameId = 0;
|
||||
encoder->lastAckframeId = 0;
|
||||
encoder->frameAck = settings->SurfaceFrameMarkerEnabled;
|
||||
|
||||
encoder->codecs |= FREERDP_CODEC_REMOTEFX;
|
||||
|
||||
return 1;
|
||||
@ -172,23 +161,24 @@ int shadow_encoder_init_nsc(rdpShadowEncoder* encoder)
|
||||
encoder->nsc = nsc_context_new();
|
||||
|
||||
if (!encoder->nsc)
|
||||
return -1;
|
||||
goto fail;
|
||||
|
||||
nsc_context_set_pixel_format(encoder->nsc, RDP_PIXEL_FORMAT_B8G8R8A8);
|
||||
|
||||
encoder->fps = 16;
|
||||
encoder->maxFps = 32;
|
||||
encoder->frameId = 0;
|
||||
encoder->lastAckframeId = 0;
|
||||
encoder->frameAck = settings->SurfaceFrameMarkerEnabled;
|
||||
if (!nsc_context_reset(encoder->nsc, encoder->width, encoder->height))
|
||||
goto fail;
|
||||
|
||||
encoder->nsc->ColorLossLevel = settings->NSCodecColorLossLevel;
|
||||
encoder->nsc->ChromaSubsamplingLevel = settings->NSCodecAllowSubsampling ? 1 : 0;
|
||||
encoder->nsc->DynamicColorFidelity = settings->NSCodecAllowDynamicColorFidelity;
|
||||
|
||||
nsc_context_set_pixel_format(encoder->nsc, RDP_PIXEL_FORMAT_B8G8R8A8);
|
||||
|
||||
encoder->codecs |= FREERDP_CODEC_NSCODEC;
|
||||
|
||||
return 1;
|
||||
|
||||
fail:
|
||||
nsc_context_free(encoder->nsc);
|
||||
return -1;
|
||||
}
|
||||
|
||||
int shadow_encoder_init_planar(rdpShadowEncoder* encoder)
|
||||
@ -209,11 +199,18 @@ int shadow_encoder_init_planar(rdpShadowEncoder* encoder)
|
||||
}
|
||||
|
||||
if (!encoder->planar)
|
||||
return -1;
|
||||
goto fail;
|
||||
|
||||
if (!freerdp_bitmap_planar_context_reset(encoder->planar))
|
||||
goto fail;
|
||||
|
||||
encoder->codecs |= FREERDP_CODEC_PLANAR;
|
||||
|
||||
return 1;
|
||||
|
||||
fail:
|
||||
freerdp_bitmap_planar_context_free(encoder->planar);
|
||||
return -1;
|
||||
}
|
||||
|
||||
int shadow_encoder_init_interleaved(rdpShadowEncoder* encoder)
|
||||
@ -222,11 +219,43 @@ int shadow_encoder_init_interleaved(rdpShadowEncoder* encoder)
|
||||
encoder->interleaved = bitmap_interleaved_context_new(TRUE);
|
||||
|
||||
if (!encoder->interleaved)
|
||||
return -1;
|
||||
goto fail;
|
||||
|
||||
if (!bitmap_interleaved_context_reset(encoder->interleaved))
|
||||
goto fail;
|
||||
|
||||
encoder->codecs |= FREERDP_CODEC_INTERLEAVED;
|
||||
|
||||
return 1;
|
||||
|
||||
fail:
|
||||
bitmap_interleaved_context_free(encoder->interleaved);
|
||||
return -1;
|
||||
}
|
||||
|
||||
int shadow_encoder_init_h264(rdpShadowEncoder* encoder)
|
||||
{
|
||||
if (!encoder->h264)
|
||||
encoder->h264 = h264_context_new(TRUE);
|
||||
|
||||
if (!encoder->h264)
|
||||
goto fail;
|
||||
|
||||
if (!h264_context_reset(encoder->h264, encoder->width, encoder->height))
|
||||
goto fail;
|
||||
|
||||
encoder->h264->RateControlMode = encoder->server->h264RateControlMode;
|
||||
encoder->h264->BitRate = encoder->server->h264BitRate;
|
||||
encoder->h264->FrameRate = encoder->server->h264FrameRate;
|
||||
encoder->h264->QP = encoder->server->h264QP;
|
||||
|
||||
encoder->codecs |= FREERDP_CODEC_AVC420;
|
||||
|
||||
return 1;
|
||||
|
||||
fail:
|
||||
h264_context_free(encoder->h264);
|
||||
return -1;
|
||||
}
|
||||
|
||||
int shadow_encoder_init(rdpShadowEncoder* encoder)
|
||||
@ -300,6 +329,19 @@ int shadow_encoder_uninit_interleaved(rdpShadowEncoder* encoder)
|
||||
return 1;
|
||||
}
|
||||
|
||||
int shadow_encoder_uninit_h264(rdpShadowEncoder* encoder)
|
||||
{
|
||||
if (encoder->h264)
|
||||
{
|
||||
h264_context_free(encoder->h264);
|
||||
encoder->h264= NULL;
|
||||
}
|
||||
|
||||
encoder->codecs &= ~FREERDP_CODEC_AVC420;
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
int shadow_encoder_uninit(rdpShadowEncoder* encoder)
|
||||
{
|
||||
shadow_encoder_uninit_grid(encoder);
|
||||
@ -330,6 +372,11 @@ int shadow_encoder_uninit(rdpShadowEncoder* encoder)
|
||||
shadow_encoder_uninit_interleaved(encoder);
|
||||
}
|
||||
|
||||
if (encoder->codecs & FREERDP_CODEC_AVC420)
|
||||
{
|
||||
shadow_encoder_uninit_h264(encoder);
|
||||
}
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
@ -337,6 +384,8 @@ int shadow_encoder_reset(rdpShadowEncoder* encoder)
|
||||
{
|
||||
int status;
|
||||
UINT32 codecs = encoder->codecs;
|
||||
rdpContext* context = (rdpContext*) encoder->client;
|
||||
rdpSettings* settings = context->settings;
|
||||
|
||||
status = shadow_encoder_uninit(encoder);
|
||||
|
||||
@ -353,6 +402,12 @@ int shadow_encoder_reset(rdpShadowEncoder* encoder)
|
||||
if (status < 0)
|
||||
return -1;
|
||||
|
||||
encoder->fps = 16;
|
||||
encoder->maxFps = 32;
|
||||
encoder->frameId = 0;
|
||||
encoder->lastAckframeId = 0;
|
||||
encoder->frameAck = settings->SurfaceFrameMarkerEnabled;
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
@ -392,6 +447,14 @@ int shadow_encoder_prepare(rdpShadowEncoder* encoder, UINT32 codecs)
|
||||
return -1;
|
||||
}
|
||||
|
||||
if ((codecs & FREERDP_CODEC_AVC420) && !(encoder->codecs & FREERDP_CODEC_AVC420))
|
||||
{
|
||||
status = shadow_encoder_init_h264(encoder);
|
||||
|
||||
if (status < 0)
|
||||
return -1;
|
||||
}
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
|
@ -49,6 +49,7 @@ struct rdp_shadow_encoder
|
||||
NSC_CONTEXT* nsc;
|
||||
BITMAP_PLANAR_CONTEXT* planar;
|
||||
BITMAP_INTERLEAVED_CONTEXT* interleaved;
|
||||
H264_CONTEXT* h264;
|
||||
|
||||
int fps;
|
||||
int maxFps;
|
||||
|
98
server/shadow/shadow_rdpgfx.c
Normal file
98
server/shadow/shadow_rdpgfx.c
Normal file
@ -0,0 +1,98 @@
|
||||
/**
|
||||
* FreeRDP: A Remote Desktop Protocol Implementation
|
||||
*
|
||||
* Copyright 2016 Jiang Zihao <zihao.jiang@yahoo.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
|
||||
|
||||
#include <freerdp/log.h>
|
||||
#include "shadow.h"
|
||||
|
||||
#include "shadow_rdpgfx.h"
|
||||
|
||||
#define TAG SERVER_TAG("shadow")
|
||||
|
||||
/**
|
||||
* Function description
|
||||
*
|
||||
* @return 0 on success, otherwise a Win32 error code
|
||||
*/
|
||||
static UINT rdpgfx_caps_advertise(RdpgfxServerContext* context, RDPGFX_CAPS_ADVERTISE_PDU* capsAdvertise)
|
||||
{
|
||||
UINT16 index;
|
||||
RDPGFX_CAPS_CONFIRM_PDU pdu;
|
||||
rdpSettings* settings = context->rdpcontext->settings;
|
||||
UINT32 flags = 0;
|
||||
|
||||
for (index = 0; index < capsAdvertise->capsSetCount; index++)
|
||||
{
|
||||
pdu.capsSet = &(capsAdvertise->capsSets[index]);
|
||||
if (pdu.capsSet->version == RDPGFX_CAPVERSION_10)
|
||||
{
|
||||
if (settings)
|
||||
{
|
||||
flags = pdu.capsSet->flags;
|
||||
settings->GfxSmallCache = (flags & RDPGFX_CAPS_FLAG_SMALL_CACHE);
|
||||
settings->GfxH264 = !(flags & RDPGFX_CAPS_FLAG_AVC_DISABLED);
|
||||
}
|
||||
|
||||
return context->CapsConfirm(context, &pdu);
|
||||
}
|
||||
else if (pdu.capsSet->version == RDPGFX_CAPVERSION_81)
|
||||
{
|
||||
if (settings)
|
||||
{
|
||||
flags = pdu.capsSet->flags;
|
||||
settings->GfxThinClient = (flags & RDPGFX_CAPS_FLAG_THINCLIENT);
|
||||
settings->GfxSmallCache = (flags & RDPGFX_CAPS_FLAG_SMALL_CACHE);
|
||||
settings->GfxH264 = (flags & RDPGFX_CAPS_FLAG_AVC420_ENABLED);
|
||||
}
|
||||
|
||||
return context->CapsConfirm(context, &pdu);
|
||||
}
|
||||
}
|
||||
|
||||
return CHANNEL_RC_UNSUPPORTED_VERSION;
|
||||
}
|
||||
|
||||
int shadow_client_rdpgfx_init(rdpShadowClient* client)
|
||||
{
|
||||
RdpgfxServerContext* rdpgfx;
|
||||
rdpgfx = client->rdpgfx = rdpgfx_server_context_new(client->vcm);
|
||||
if (!rdpgfx)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
rdpgfx->rdpcontext = &client->context;
|
||||
|
||||
rdpgfx->custom = client;
|
||||
|
||||
rdpgfx->CapsAdvertise = rdpgfx_caps_advertise;
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
void shadow_client_rdpgfx_uninit(rdpShadowClient* client)
|
||||
{
|
||||
if (client->rdpgfx)
|
||||
{
|
||||
rdpgfx_server_context_free(client->rdpgfx);
|
||||
client->rdpgfx = NULL;
|
||||
}
|
||||
}
|
38
server/shadow/shadow_rdpgfx.h
Normal file
38
server/shadow/shadow_rdpgfx.h
Normal file
@ -0,0 +1,38 @@
|
||||
/**
|
||||
* FreeRDP: A Remote Desktop Protocol Implementation
|
||||
*
|
||||
* Copyright 2016 Jiang Zihao <zihao.jiang@yahoo.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.
|
||||
*/
|
||||
|
||||
#ifndef FREERDP_SHADOW_SERVER_RDPGFX_H
|
||||
#define FREERDP_SHADOW_SERVER_RDPGFX_H
|
||||
|
||||
#include <freerdp/server/shadow.h>
|
||||
|
||||
#include <winpr/crt.h>
|
||||
#include <winpr/synch.h>
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
int shadow_client_rdpgfx_init(rdpShadowClient* client);
|
||||
void shadow_client_rdpgfx_uninit(rdpShadowClient* client);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif /* FREERDP_SHADOW_SERVER_RDPGFX_H */
|
@ -769,6 +769,12 @@ rdpShadowServer* shadow_server_new()
|
||||
server->mayView = TRUE;
|
||||
server->mayInteract = TRUE;
|
||||
|
||||
server->rfxMode = RLGR3;
|
||||
server->h264RateControlMode = H264_RATECONTROL_VBR;
|
||||
server->h264BitRate = 1000000;
|
||||
server->h264FrameRate = 30;
|
||||
server->h264QP = 0;
|
||||
|
||||
server->authentication = FALSE;
|
||||
|
||||
server->settings = freerdp_settings_new(FREERDP_SETTINGS_SERVER_MODE);
|
||||
|
@ -86,8 +86,6 @@ int shadow_subsystem_init(rdpShadowSubsystem* subsystem, rdpShadowServer* server
|
||||
if (!(subsystem->updateEvent = shadow_multiclient_new()))
|
||||
goto fail;
|
||||
|
||||
region16_init(&(subsystem->invalidRegion));
|
||||
|
||||
if ((status = subsystem->ep.Init(subsystem)) >= 0)
|
||||
return status;
|
||||
|
||||
@ -141,9 +139,6 @@ void shadow_subsystem_uninit(rdpShadowSubsystem* subsystem)
|
||||
shadow_multiclient_free(subsystem->updateEvent);
|
||||
subsystem->updateEvent = NULL;
|
||||
}
|
||||
|
||||
if (subsystem->invalidRegion.data)
|
||||
region16_uninit(&(subsystem->invalidRegion));
|
||||
}
|
||||
|
||||
int shadow_subsystem_start(rdpShadowSubsystem* subsystem)
|
||||
|
Loading…
Reference in New Issue
Block a user