diff --git a/include/freerdp/codec/rfx.h b/include/freerdp/codec/rfx.h index 108765bad..c6c9213a9 100644 --- a/include/freerdp/codec/rfx.h +++ b/include/freerdp/codec/rfx.h @@ -71,108 +71,26 @@ extern "C" BYTE* YCbCrData; } RFX_TILE; - typedef struct - { - UINT32 frameIdx; - - /** - * The rects array represents the updated region of the frame. The UI - * requires to clip drawing destination base on the union of the rects. - */ - UINT16 numRects; - RFX_RECT* rects; - BOOL freeRects; - - /** - * The tiles array represents the actual frame data. Each tile is always - * 64x64. Note that only pixels inside the updated region (represented as - * rects described above) are valid. Pixels outside of the region may - * contain arbitrary data. - */ - UINT16 numTiles; - size_t allocatedTiles; - RFX_TILE** tiles; - - UINT16 numQuant; - UINT32* quantVals; - - UINT32 tilesDataSize; - - BOOL freeArray; - } RFX_MESSAGE; - - typedef struct S_RFX_CONTEXT_PRIV RFX_CONTEXT_PRIV; - - typedef enum - { - RFX_STATE_INITIAL, - RFX_STATE_SERVER_UNINITIALIZED, - RFX_STATE_SEND_HEADERS, - RFX_STATE_SEND_FRAME_DATA, - RFX_STATE_FRAME_DATA_SENT, - RFX_STATE_FINAL - } RFX_STATE; - -#define RFX_DECODED_SYNC 0x00000001 -#define RFX_DECODED_CONTEXT 0x00000002 -#define RFX_DECODED_VERSIONS 0x00000004 -#define RFX_DECODED_CHANNELS 0x00000008 -#define RFX_DECODED_HEADERS 0x0000000F - - typedef struct - { - RFX_STATE state; - - BOOL encoder; - UINT16 flags; - UINT16 properties; - UINT16 width; - UINT16 height; - RLGR_MODE mode; - UINT32 version; - UINT32 codec_id; - UINT32 codec_version; - UINT32 pixel_format; - BYTE bits_per_pixel; - - /* color palette allocated by the application */ - const BYTE* palette; - - /* temporary data within a frame */ - UINT32 frameIdx; - BYTE numQuant; - UINT32* quants; - BYTE quantIdxY; - BYTE quantIdxCb; - BYTE quantIdxCr; - - /* decoded header blocks */ - UINT32 decodedHeaderBlocks; - UINT16 expectedDataBlockType; - RFX_MESSAGE currentMessage; - - /* routines */ - void (*quantization_decode)(INT16* buffer, const UINT32* quantization_values); - void (*quantization_encode)(INT16* buffer, const UINT32* quantization_values); - void (*dwt_2d_decode)(INT16* buffer, INT16* dwt_buffer); - void (*dwt_2d_encode)(INT16* buffer, INT16* dwt_buffer); - int (*rlgr_decode)(RLGR_MODE mode, const BYTE* data, UINT32 data_size, INT16* buffer, - UINT32 buffer_size); - int (*rlgr_encode)(RLGR_MODE mode, const INT16* data, UINT32 data_size, BYTE* buffer, - UINT32 buffer_size); - - /* private definitions */ - RFX_CONTEXT_PRIV* priv; - } RFX_CONTEXT; - - FREERDP_API void rfx_context_set_pixel_format(RFX_CONTEXT* context, UINT32 pixel_format); + typedef struct S_RFX_MESSAGE_LIST RFX_MESSAGE_LIST; + typedef struct S_RFX_MESSAGE RFX_MESSAGE; + typedef struct S_RFX_CONTEXT RFX_CONTEXT; FREERDP_API BOOL rfx_process_message(RFX_CONTEXT* context, const BYTE* data, UINT32 length, UINT32 left, UINT32 top, BYTE* dst, UINT32 dstFormat, UINT32 dstStride, UINT32 dstHeight, REGION16* invalidRegion); - FREERDP_API UINT16 rfx_message_get_tile_count(RFX_MESSAGE* message); - FREERDP_API UINT16 rfx_message_get_rect_count(RFX_MESSAGE* message); + + FREERDP_API UINT32 rfx_message_get_frame_idx(const RFX_MESSAGE* message); + FREERDP_API const UINT32* rfx_message_get_quants(const RFX_MESSAGE* message, + UINT16* numQuantVals); + + FREERDP_API const RFX_TILE** rfx_message_get_tiles(const RFX_MESSAGE* message, + UINT16* numTiles); + FREERDP_API UINT16 rfx_message_get_tile_count(const RFX_MESSAGE* message); + + FREERDP_API const RFX_RECT* rfx_message_get_rects(const RFX_MESSAGE* message, UINT16* numRects); + FREERDP_API UINT16 rfx_message_get_rect_count(const RFX_MESSAGE* message); + FREERDP_API void rfx_message_free(RFX_CONTEXT* context, RFX_MESSAGE* message); FREERDP_API BOOL rfx_compose_message(RFX_CONTEXT* context, wStream* s, const RFX_RECT* rects, @@ -183,19 +101,27 @@ extern "C" size_t numRects, const BYTE* data, UINT32 width, UINT32 height, size_t scanline); - FREERDP_API RFX_MESSAGE* rfx_encode_messages(RFX_CONTEXT* context, const RFX_RECT* rects, - size_t numRects, const BYTE* data, UINT32 width, - UINT32 height, UINT32 scanline, - size_t* numMessages, size_t maxDataSize); + FREERDP_API RFX_MESSAGE_LIST* rfx_encode_messages(RFX_CONTEXT* context, const RFX_RECT* rects, + size_t numRects, const BYTE* data, + UINT32 width, UINT32 height, UINT32 scanline, + size_t* numMessages, size_t maxDataSize); + FREERDP_API void rfx_message_list_free(RFX_MESSAGE_LIST* messages); + + FREERDP_API const RFX_MESSAGE* rfx_message_list_get(const RFX_MESSAGE_LIST* messages, + size_t idx); + FREERDP_API BOOL rfx_write_message(RFX_CONTEXT* context, wStream* s, const RFX_MESSAGE* message); - FREERDP_API BOOL rfx_context_reset(RFX_CONTEXT* context, UINT32 width, UINT32 height); - FREERDP_API RFX_CONTEXT* rfx_context_new_ex(BOOL encoder, UINT32 ThreadingFlags); FREERDP_API RFX_CONTEXT* rfx_context_new(BOOL encoder); FREERDP_API void rfx_context_free(RFX_CONTEXT* context); + FREERDP_API BOOL rfx_context_reset(RFX_CONTEXT* context, UINT32 width, UINT32 height); + FREERDP_API BOOL rfx_context_set_mode(RFX_CONTEXT* context, RLGR_MODE mode); + FREERDP_API void rfx_context_set_pixel_format(RFX_CONTEXT* context, UINT32 pixel_format); + FREERDP_API UINT32 rfx_context_get_frame_idx(const RFX_CONTEXT* context); + #ifdef __cplusplus } #endif diff --git a/libfreerdp/codec/rfx.c b/libfreerdp/codec/rfx.c index 70c9ceb56..635f8d21a 100644 --- a/libfreerdp/codec/rfx.c +++ b/libfreerdp/codec/rfx.c @@ -1288,13 +1288,37 @@ BOOL rfx_process_message(RFX_CONTEXT* context, const BYTE* data, UINT32 length, return FALSE; } -UINT16 rfx_message_get_tile_count(RFX_MESSAGE* message) +const UINT32* rfx_message_get_quants(const RFX_MESSAGE* message, UINT16* numQuantVals) +{ + WINPR_ASSERT(message); + if (numQuantVals) + *numQuantVals = message->numQuant; + return message->quantVals; +} + +const RFX_TILE** rfx_message_get_tiles(const RFX_MESSAGE* message, UINT16* numTiles) +{ + WINPR_ASSERT(message); + if (numTiles) + *numTiles = message->numTiles; + return message->tiles; +} + +UINT16 rfx_message_get_tile_count(const RFX_MESSAGE* message) { WINPR_ASSERT(message); return message->numTiles; } -UINT16 rfx_message_get_rect_count(RFX_MESSAGE* message) +const RFX_RECT* rfx_message_get_rects(const RFX_MESSAGE* message, UINT16* numRects) +{ + WINPR_ASSERT(message); + if (numRects) + *numRects = message->numRects; + return message->rects; +} + +UINT16 rfx_message_get_rect_count(const RFX_MESSAGE* message) { WINPR_ASSERT(message); return message->numRects; @@ -1427,7 +1451,6 @@ static BOOL rfx_write_tile(RFX_CONTEXT* context, wStream* s, RFX_TILE* tile) if (!Stream_EnsureRemainingCapacity(s, blockLen)) return FALSE; - WINPR_ASSERT(tile); Stream_Write_UINT16(s, CBT_TILE); /* BlockT.blockType (2 bytes) */ Stream_Write_UINT32(s, blockLen); /* BlockT.blockLen (4 bytes) */ Stream_Write_UINT8(s, tile->quantIdxY); /* quantIdxY (1 byte) */ @@ -1815,25 +1838,55 @@ free_messages: return NULL; } -RFX_MESSAGE* rfx_encode_messages(RFX_CONTEXT* context, const RFX_RECT* rects, size_t numRects, - const BYTE* data, UINT32 width, UINT32 height, UINT32 scanline, - size_t* numMessages, size_t maxDataSize) +const RFX_MESSAGE* rfx_message_list_get(const RFX_MESSAGE_LIST* messages, size_t idx) { + WINPR_ASSERT(messages); + if (idx >= messages->count) + return NULL; + WINPR_ASSERT(messages->list); + return &messages->list[idx]; +} + +void rfx_message_list_free(RFX_MESSAGE_LIST* messages) +{ + if (!messages) + return; + for (size_t x = 0; x < messages->count; x++) + rfx_message_free(messages->context, &messages->list[x]); + free(messages); +} + +static RFX_MESSAGE_LIST* rfx_message_list_new(RFX_CONTEXT* context, RFX_MESSAGE* messages, + size_t count) +{ + WINPR_ASSERT(context); + RFX_MESSAGE_LIST* msg = calloc(1, sizeof(RFX_MESSAGE_LIST)); + WINPR_ASSERT(msg); + + msg->context = context; + msg->count = count; + msg->list = messages; + return msg; +} + +RFX_MESSAGE_LIST* rfx_encode_messages(RFX_CONTEXT* context, const RFX_RECT* rects, size_t numRects, + const BYTE* data, UINT32 width, UINT32 height, + UINT32 scanline, size_t* numMessages, size_t maxDataSize) +{ + WINPR_ASSERT(context); + WINPR_ASSERT(numMessages); RFX_MESSAGE* message = rfx_encode_message(context, rects, numRects, data, width, height, scanline); if (!message) return NULL; - RFX_MESSAGE* messageList = rfx_split_message(context, message, numMessages, maxDataSize); - if (!messageList) - { - rfx_message_free(context, message); - return NULL; - } - + RFX_MESSAGE* list = rfx_split_message(context, message, numMessages, maxDataSize); rfx_message_free(context, message); - return messageList; + if (!list) + return NULL; + + return rfx_message_list_new(context, list, *numMessages); } static BOOL rfx_write_message_tileset(RFX_CONTEXT* context, wStream* s, const RFX_MESSAGE* message) @@ -1989,3 +2042,22 @@ BOOL rfx_compose_message(RFX_CONTEXT* context, wStream* s, const RFX_RECT* rects rfx_message_free(context, message); return ret; } + +BOOL rfx_context_set_mode(RFX_CONTEXT* context, RLGR_MODE mode) +{ + WINPR_ASSERT(context); + context->mode = mode; + return TRUE; +} + +UINT32 rfx_context_get_frame_idx(const RFX_CONTEXT* context) +{ + WINPR_ASSERT(context); + return context->frameIdx; +} + +UINT32 rfx_message_get_frame_idx(const RFX_MESSAGE* message) +{ + WINPR_ASSERT(message); + return message->frameIdx; +} diff --git a/libfreerdp/codec/rfx_types.h b/libfreerdp/codec/rfx_types.h index 34f9955bf..66a10b7fb 100644 --- a/libfreerdp/codec/rfx_types.h +++ b/libfreerdp/codec/rfx_types.h @@ -27,6 +27,7 @@ #include #include +#include #include #include @@ -40,8 +41,25 @@ } while (0) #endif +#define RFX_DECODED_SYNC 0x00000001 +#define RFX_DECODED_CONTEXT 0x00000002 +#define RFX_DECODED_VERSIONS 0x00000004 +#define RFX_DECODED_CHANNELS 0x00000008 +#define RFX_DECODED_HEADERS 0x0000000F + +typedef enum +{ + RFX_STATE_INITIAL, + RFX_STATE_SERVER_UNINITIALIZED, + RFX_STATE_SEND_HEADERS, + RFX_STATE_SEND_FRAME_DATA, + RFX_STATE_FRAME_DATA_SENT, + RFX_STATE_FINAL +} RFX_STATE; + typedef struct S_RFX_TILE_COMPOSE_WORK_PARAM RFX_TILE_COMPOSE_WORK_PARAM; +typedef struct S_RFX_CONTEXT_PRIV RFX_CONTEXT_PRIV; struct S_RFX_CONTEXT_PRIV { wLog* log; @@ -78,4 +96,87 @@ struct S_RFX_CONTEXT_PRIV PROFILER_DEFINE(prof_rfx_encode_format_rgb) }; +struct S_RFX_MESSAGE +{ + UINT32 frameIdx; + + /** + * The rects array represents the updated region of the frame. The UI + * requires to clip drawing destination base on the union of the rects. + */ + UINT16 numRects; + RFX_RECT* rects; + BOOL freeRects; + + /** + * The tiles array represents the actual frame data. Each tile is always + * 64x64. Note that only pixels inside the updated region (represented as + * rects described above) are valid. Pixels outside of the region may + * contain arbitrary data. + */ + UINT16 numTiles; + size_t allocatedTiles; + RFX_TILE** tiles; + + UINT16 numQuant; + UINT32* quantVals; + + UINT32 tilesDataSize; + + BOOL freeArray; +}; + +struct S_RFX_MESSAGE_LIST +{ + struct S_RFX_MESSAGE* list; + size_t count; + RFX_CONTEXT* context; +}; + +struct S_RFX_CONTEXT +{ + RFX_STATE state; + + BOOL encoder; + UINT16 flags; + UINT16 properties; + UINT16 width; + UINT16 height; + RLGR_MODE mode; + UINT32 version; + UINT32 codec_id; + UINT32 codec_version; + UINT32 pixel_format; + BYTE bits_per_pixel; + + /* color palette allocated by the application */ + const BYTE* palette; + + /* temporary data within a frame */ + UINT32 frameIdx; + BYTE numQuant; + UINT32* quants; + BYTE quantIdxY; + BYTE quantIdxCb; + BYTE quantIdxCr; + + /* decoded header blocks */ + UINT32 decodedHeaderBlocks; + UINT16 expectedDataBlockType; + struct S_RFX_MESSAGE currentMessage; + + /* routines */ + void (*quantization_decode)(INT16* buffer, const UINT32* quantization_values); + void (*quantization_encode)(INT16* buffer, const UINT32* quantization_values); + void (*dwt_2d_decode)(INT16* buffer, INT16* dwt_buffer); + void (*dwt_2d_encode)(INT16* buffer, INT16* dwt_buffer); + int (*rlgr_decode)(RLGR_MODE mode, const BYTE* data, UINT32 data_size, INT16* buffer, + UINT32 buffer_size); + int (*rlgr_encode)(RLGR_MODE mode, const INT16* data, UINT32 data_size, BYTE* buffer, + UINT32 buffer_size); + + /* private definitions */ + RFX_CONTEXT_PRIV* priv; +}; + #endif /* FREERDP_LIB_CODEC_RFX_TYPES_H */ diff --git a/server/Sample/sfreerdp.c b/server/Sample/sfreerdp.c index 85ce4f07a..b23aa4eb5 100644 --- a/server/Sample/sfreerdp.c +++ b/server/Sample/sfreerdp.c @@ -122,7 +122,7 @@ static BOOL test_peer_context_new(freerdp_peer* client, rdpContext* ctx) SAMPLE_SERVER_DEFAULT_HEIGHT)) goto fail; - context->rfx_context->mode = RLGR3; + rfx_context_set_mode(context->rfx_context, RLGR3); rfx_context_set_pixel_format(context->rfx_context, PIXEL_FORMAT_RGB24); if (!(context->nsc_context = nsc_context_new())) diff --git a/server/Windows/wf_update.c b/server/Windows/wf_update.c index a301b582f..136cefacd 100644 --- a/server/Windows/wf_update.c +++ b/server/Windows/wf_update.c @@ -130,7 +130,7 @@ void wf_update_encode(wfInfo* wfi) return; } - wfi->frame_idx = wfi->rfx_context->frameIdx; + wfi->frame_idx = rfx_context_get_frame_idx(wfi->rfx_context); cmd->destLeft = wfi->invalid.left; cmd->destTop = wfi->invalid.top; cmd->destRight = wfi->invalid.left + width; @@ -199,9 +199,8 @@ void wf_update_encoder_reset(wfInfo* wfi) { /* TODO: pass ThreadingFlags somehow */ 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_mode(wfi->rfx_context, RLGR3); + rfx_context_reset(wfi->rfx_context, wfi->servscreen_width, wfi->servscreen_height); rfx_context_set_pixel_format(wfi->rfx_context, PIXEL_FORMAT_BGRA32); wfi->s = Stream_New(NULL, 0xFFFF); } diff --git a/server/shadow/shadow_client.c b/server/shadow/shadow_client.c index d08c65d83..e23f86c33 100644 --- a/server/shadow/shadow_client.c +++ b/server/shadow/shadow_client.c @@ -1323,7 +1323,6 @@ static BOOL shadow_client_send_surface_bits(rdpShadowClient* client, BYTE* pSrcD UINT16 nWidth, UINT16 nHeight) { BOOL ret = TRUE; - size_t i; BOOL first; BOOL last; wStream* s; @@ -1353,9 +1352,7 @@ static BOOL shadow_client_send_surface_bits(rdpShadowClient* client, BYTE* pSrcD rfxID = freerdp_settings_get_uint32(settings, FreeRDP_RemoteFxCodecId); if (freerdp_settings_get_bool(settings, FreeRDP_RemoteFxCodec) && (rfxID != 0)) { - RFX_RECT rect; - RFX_MESSAGE* messages; - RFX_RECT* messageRects = NULL; + RFX_RECT rect = { 0 }; if (shadow_encoder_prepare(encoder, FREERDP_CODEC_REMOTEFX) < 0) { @@ -1369,9 +1366,10 @@ static BOOL shadow_client_send_surface_bits(rdpShadowClient* client, BYTE* pSrcD rect.width = nWidth; rect.height = nHeight; - if (!(messages = rfx_encode_messages( - encoder->rfx, &rect, 1, pSrcData, settings->DesktopWidth, settings->DesktopHeight, - nSrcStep, &numMessages, settings->MultifragMaxRequestSize))) + RFX_MESSAGE_LIST* messages = rfx_encode_messages( + encoder->rfx, &rect, 1, pSrcData, settings->DesktopWidth, settings->DesktopHeight, + nSrcStep, &numMessages, settings->MultifragMaxRequestSize); + if (!messages) { WLog_ERR(TAG, "rfx_encode_messages failed"); return FALSE; @@ -1392,26 +1390,19 @@ static BOOL shadow_client_send_surface_bits(rdpShadowClient* client, BYTE* pSrcD cmd.bmp.height = (UINT16)settings->DesktopHeight; cmd.skipCompression = TRUE; - if (numMessages > 0) - messageRects = messages[0].rects; - - for (i = 0; i < numMessages; i++) + for (size_t i = 0; i < numMessages; i++) { Stream_SetPosition(s, 0); - if (!rfx_write_message(encoder->rfx, s, &messages[i])) + const RFX_MESSAGE* msg = rfx_message_list_get(messages, i); + if (!rfx_write_message(encoder->rfx, s, msg)) { - while (i < numMessages) - { - rfx_message_free(encoder->rfx, &messages[i++]); - } - + rfx_message_list_free(messages); WLog_ERR(TAG, "rfx_write_message failed"); ret = FALSE; break; } - rfx_message_free(encoder->rfx, &messages[i]); WINPR_ASSERT(Stream_GetPosition(s) <= UINT32_MAX); cmd.bmp.bitmapDataLength = (UINT32)Stream_GetPosition(s); cmd.bmp.bitmapData = Stream_Buffer(s); @@ -1431,8 +1422,7 @@ static BOOL shadow_client_send_surface_bits(rdpShadowClient* client, BYTE* pSrcD } } - free(messageRects); - free(messages); + rfx_message_list_free(messages); } if (freerdp_settings_get_bool(settings, FreeRDP_NSCodec) && (nsID != 0)) { diff --git a/server/shadow/shadow_encoder.c b/server/shadow/shadow_encoder.c index 83e83f966..684c3f1a3 100644 --- a/server/shadow/shadow_encoder.c +++ b/server/shadow/shadow_encoder.c @@ -140,7 +140,7 @@ static int shadow_encoder_init_rfx(rdpShadowEncoder* encoder) if (!rfx_context_reset(encoder->rfx, encoder->width, encoder->height)) goto fail; - encoder->rfx->mode = encoder->server->rfxMode; + rfx_context_set_mode(encoder->rfx, encoder->server->rfxMode); rfx_context_set_pixel_format(encoder->rfx, PIXEL_FORMAT_BGRX32); encoder->codecs |= FREERDP_CODEC_REMOTEFX; return 1;