[codec,rfx] refactor API

* Hide implementation details
* Add missing getter/setter
This commit is contained in:
Armin Novak 2023-04-05 13:47:59 +02:00 committed by akallabeth
parent a86218c761
commit f66110c611
7 changed files with 231 additions and 143 deletions

View File

@ -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,
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

View File

@ -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* list = rfx_split_message(context, message, numMessages, maxDataSize);
rfx_message_free(context, message);
if (!list)
return NULL;
}
rfx_message_free(context, message);
return messageList;
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;
}

View File

@ -27,6 +27,7 @@
#include <winpr/wlog.h>
#include <winpr/collections.h>
#include <freerdp/codec/rfx.h>
#include <freerdp/log.h>
#include <freerdp/utils/profiler.h>
@ -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 */

View File

@ -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()))

View File

@ -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);
}

View File

@ -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(
RFX_MESSAGE_LIST* messages = rfx_encode_messages(
encoder->rfx, &rect, 1, pSrcData, settings->DesktopWidth, settings->DesktopHeight,
nSrcStep, &numMessages, settings->MultifragMaxRequestSize)))
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))
{

View File

@ -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;