Added PROGRESSIVE codec to shadow

This commit is contained in:
Armin Novak 2021-06-28 14:45:19 +02:00 committed by akallabeth
parent 7afc91650e
commit 98ed05ff5c
4 changed files with 286 additions and 85 deletions

View File

@ -1826,6 +1826,170 @@ static INLINE int progressive_process_tiles(PROGRESSIVE_CONTEXT* progressive, wS
return (int)(end - start);
}
static INLINE BOOL progressive_write_wb_sync(PROGRESSIVE_CONTEXT* progressive, wStream* s)
{
const UINT32 blockLen = 12;
WINPR_ASSERT(progressive);
WINPR_ASSERT(s);
if (!Stream_EnsureRemainingCapacity(s, blockLen))
return FALSE;
Stream_Write_UINT16(s, PROGRESSIVE_WBT_SYNC); /* blockType (2 bytes) */
Stream_Write_UINT32(s, blockLen); /* blockLen (4 bytes) */
Stream_Write_UINT32(s, 0xCACCACCA); /* magic (4 bytes) */
Stream_Write_UINT16(s, 0x0100); /* version (2 bytes) */
return TRUE;
}
static INLINE BOOL progressive_write_wb_context(PROGRESSIVE_CONTEXT* progressive, wStream* s)
{
const UINT32 blockLen = 10;
WINPR_ASSERT(progressive);
WINPR_ASSERT(s);
if (!Stream_EnsureRemainingCapacity(s, blockLen))
return FALSE;
Stream_Write_UINT16(s, PROGRESSIVE_WBT_CONTEXT); /* blockType (2 bytes) */
Stream_Write_UINT32(s, blockLen); /* blockLen (4 bytes) */
Stream_Write_UINT8(s, 0); /* ctxId (1 byte) */
Stream_Write_UINT16(s, 64); /* tileSize (2 bytes) */
Stream_Write_UINT8(s, 0); /* flags (1 byte) */
return TRUE;
}
static INLINE BOOL progressive_write_region(PROGRESSIVE_CONTEXT* progressive, wStream* s,
const RFX_MESSAGE* msg)
{
/* RFX_PROGRESSIVE_REGION */
UINT32 blockLen = 18;
UINT16 i;
UINT32* qv;
UINT32 tilesDataSize;
WINPR_ASSERT(progressive);
WINPR_ASSERT(s);
WINPR_ASSERT(msg);
blockLen += msg->numRects * 8;
blockLen += msg->numQuant * 5;
tilesDataSize = msg->numTiles * 22UL;
for (i = 0; i < msg->numTiles; i++)
{
const RFX_TILE* tile = msg->tiles[i];
WINPR_ASSERT(tile);
tilesDataSize += tile->YLen + tile->CbLen + tile->CrLen;
}
blockLen += tilesDataSize;
if (!Stream_EnsureRemainingCapacity(s, blockLen))
return FALSE;
Stream_Write_UINT16(s, PROGRESSIVE_WBT_REGION); /* blockType (2 bytes) */
Stream_Write_UINT32(s, blockLen); /* blockLen (4 bytes) */
Stream_Write_UINT8(s, 64); /* tileSize (1 byte) */
Stream_Write_UINT16(s, msg->numRects); /* numRects (2 bytes) */
Stream_Write_UINT8(s, msg->numQuant); /* numQuant (1 byte) */
Stream_Write_UINT8(s, 0); /* numProgQuant (1 byte) */
Stream_Write_UINT8(s, 0); /* flags (1 byte) */
Stream_Write_UINT16(s, msg->numTiles); /* numTiles (2 bytes) */
Stream_Write_UINT32(s, tilesDataSize); /* tilesDataSize (4 bytes) */
for (i = 0; i < msg->numRects; i++)
{
/* TS_RFX_RECT */
Stream_Write_UINT16(s, msg->rects[i].x); /* x (2 bytes) */
Stream_Write_UINT16(s, msg->rects[i].y); /* y (2 bytes) */
Stream_Write_UINT16(s, msg->rects[i].width); /* width (2 bytes) */
Stream_Write_UINT16(s, msg->rects[i].height); /* height (2 bytes) */
}
/**
* Note: The RFX_COMPONENT_CODEC_QUANT structure differs from the
* TS_RFX_CODEC_QUANT ([MS-RDPRFX] section 2.2.2.1.5) structure with respect
* to the order of the bands.
* 0 1 2 3 4 5 6 7 8 9
* RDPRFX: LL3, LH3, HL3, HH3, LH2, HL2, HH2, LH1, HL1, HH1
* RDPEGFX: LL3, HL3, LH3, HH3, HL2, LH2, HH2, HL1, LH1, HH1
*/
for (i = 0, qv = msg->quantVals; i < msg->numQuant; i++, qv += 10)
{
/* RFX_COMPONENT_CODEC_QUANT */
Stream_Write_UINT8(s, qv[0] + (qv[2] << 4)); /* LL3 (4-bit), HL3 (4-bit) */
Stream_Write_UINT8(s, qv[1] + (qv[3] << 4)); /* LH3 (4-bit), HH3 (4-bit) */
Stream_Write_UINT8(s, qv[5] + (qv[4] << 4)); /* HL2 (4-bit), LH2 (4-bit) */
Stream_Write_UINT8(s, qv[6] + (qv[8] << 4)); /* HH2 (4-bit), HL1 (4-bit) */
Stream_Write_UINT8(s, qv[7] + (qv[9] << 4)); /* LH1 (4-bit), HH1 (4-bit) */
}
return TRUE;
}
static INLINE BOOL progressive_write_frame_begin(PROGRESSIVE_CONTEXT* progressive, wStream* s,
const RFX_MESSAGE* msg)
{
const UINT32 blockLen = 12;
WINPR_ASSERT(progressive);
WINPR_ASSERT(s);
WINPR_ASSERT(msg);
if (!Stream_EnsureRemainingCapacity(s, blockLen))
return FALSE;
Stream_Write_UINT16(s, PROGRESSIVE_WBT_FRAME_BEGIN); /* blockType (2 bytes) */
Stream_Write_UINT32(s, blockLen); /* blockLen (4 bytes) */
Stream_Write_UINT32(s, msg->frameIdx); /* frameIndex (4 bytes) */
Stream_Write_UINT16(s, 1); /* regionCount (2 bytes) */
return TRUE;
}
static INLINE BOOL progressive_write_frame_end(PROGRESSIVE_CONTEXT* progressive, wStream* s)
{
const UINT32 blockLen = 6;
WINPR_ASSERT(progressive);
WINPR_ASSERT(s);
if (!Stream_EnsureRemainingCapacity(s, blockLen))
return FALSE;
Stream_Write_UINT16(s, PROGRESSIVE_WBT_FRAME_END); /* blockType (2 bytes) */
Stream_Write_UINT32(s, blockLen); /* blockLen (4 bytes) */
return TRUE;
}
static INLINE BOOL progressive_write_tile_simple(PROGRESSIVE_CONTEXT* progressive, wStream* s,
const RFX_TILE* tile)
{
UINT32 blockLen;
WINPR_ASSERT(progressive);
WINPR_ASSERT(s);
WINPR_ASSERT(tile);
blockLen = 22 + tile->YLen + tile->CbLen + tile->CrLen;
if (!Stream_EnsureRemainingCapacity(s, blockLen))
return FALSE;
Stream_Write_UINT16(s, PROGRESSIVE_WBT_TILE_SIMPLE); /* blockType (2 bytes) */
Stream_Write_UINT32(s, blockLen); /* blockLen (4 bytes) */
Stream_Write_UINT8(s, tile->quantIdxY); /* quantIdxY (1 byte) */
Stream_Write_UINT8(s, tile->quantIdxCb); /* quantIdxCb (1 byte) */
Stream_Write_UINT8(s, tile->quantIdxCr); /* quantIdxCr (1 byte) */
Stream_Write_UINT16(s, tile->xIdx); /* xIdx (2 bytes) */
Stream_Write_UINT16(s, tile->yIdx); /* yIdx (2 bytes) */
Stream_Write_UINT8(s, 0); /* flags (1 byte) */
Stream_Write_UINT16(s, tile->YLen); /* YLen (2 bytes) */
Stream_Write_UINT16(s, tile->CbLen); /* CbLen (2 bytes) */
Stream_Write_UINT16(s, tile->CrLen); /* CrLen (2 bytes) */
Stream_Write_UINT16(s, 0); /* tailLen (2 bytes) */
Stream_Write(s, tile->YData, tile->YLen); /* YData */
Stream_Write(s, tile->CbData, tile->CbLen); /* CbData */
Stream_Write(s, tile->CrData, tile->CrLen); /* CrData */
return TRUE;
}
static INLINE INT32 progressive_wb_sync(PROGRESSIVE_CONTEXT* progressive, wStream* s,
UINT16 blockType, UINT32 blockLen)
{
@ -2417,54 +2581,35 @@ fail:
return rc;
}
static BOOL progressive_rfx_write_message_progressive_simple(RFX_CONTEXT* context, wStream* s,
RFX_MESSAGE* msg)
static BOOL progressive_rfx_write_message_progressive_simple(PROGRESSIVE_CONTEXT* progressive,
wStream* s, const RFX_MESSAGE* msg)
{
UINT32 blockLen;
UINT32 i;
UINT32* qv;
RFX_TILE* tile;
UINT32 tilesDataSize;
RFX_CONTEXT* context;
WINPR_ASSERT(progressive);
WINPR_ASSERT(s);
WINPR_ASSERT(msg);
context = progressive->rfx_context;
WINPR_ASSERT(context);
if (context->mode != RLGR1)
{
WLog_ERR(TAG, "%s: error, RLGR1 mode is required!", __FUNCTION__);
return FALSE;
}
/* RFX_PROGRESSIVE_SYNC */
blockLen = 12;
if (!Stream_EnsureRemainingCapacity(s, blockLen))
{
if (!progressive_write_wb_sync(progressive, s))
return FALSE;
}
Stream_Write_UINT16(s, 0xCCC0); /* blockType (2 bytes) */
Stream_Write_UINT32(s, blockLen); /* blockLen (4 bytes) */
Stream_Write_UINT32(s, 0xCACCACCA); /* magic (4 bytes) */
Stream_Write_UINT16(s, 0x0100); /* version (2 bytes) */
/* RFX_PROGRESSIVE_CONTEXT */
blockLen = 10;
if (!Stream_EnsureRemainingCapacity(s, blockLen))
{
if (!progressive_write_wb_context(progressive, s))
return FALSE;
}
Stream_Write_UINT16(s, 0xCCC3); /* blockType (2 bytes) */
Stream_Write_UINT32(s, 10); /* blockLen (4 bytes) */
Stream_Write_UINT8(s, 0); /* ctxId (1 byte) */
Stream_Write_UINT16(s, 64); /* tileSize (2 bytes) */
Stream_Write_UINT8(s, 0); /* flags (1 byte) */
/* RFX_PROGRESSIVE_FRAME_BEGIN */
blockLen = 12;
if (!Stream_EnsureRemainingCapacity(s, blockLen))
{
if (!progressive_write_frame_begin(progressive, s, msg))
return FALSE;
}
Stream_Write_UINT16(s, 0xCCC1); /* blockType (2 bytes) */
Stream_Write_UINT32(s, blockLen); /* blockLen (4 bytes) */
Stream_Write_UINT32(s, msg->frameIdx); /* frameIndex (4 bytes) */
Stream_Write_UINT16(s, 1); /* regionCount (2 bytes) */
/* RFX_PROGRESSIVE_REGION */
blockLen = 18;
@ -2521,34 +2666,13 @@ static BOOL progressive_rfx_write_message_progressive_simple(RFX_CONTEXT* contex
for (i = 0; i < msg->numTiles; i++)
{
/* RFX_PROGRESSIVE_TILE_SIMPLE */
tile = msg->tiles[i];
blockLen = 22 + tile->YLen + tile->CbLen + tile->CrLen;
Stream_Write_UINT16(s, 0xCCC5); /* blockType (2 bytes) */
Stream_Write_UINT32(s, blockLen); /* blockLen (4 bytes) */
Stream_Write_UINT8(s, tile->quantIdxY); /* quantIdxY (1 byte) */
Stream_Write_UINT8(s, tile->quantIdxCb); /* quantIdxCb (1 byte) */
Stream_Write_UINT8(s, tile->quantIdxCr); /* quantIdxCr (1 byte) */
Stream_Write_UINT16(s, tile->xIdx); /* xIdx (2 bytes) */
Stream_Write_UINT16(s, tile->yIdx); /* yIdx (2 bytes) */
Stream_Write_UINT8(s, 0); /* flags (1 byte) */
Stream_Write_UINT16(s, tile->YLen); /* YLen (2 bytes) */
Stream_Write_UINT16(s, tile->CbLen); /* CbLen (2 bytes) */
Stream_Write_UINT16(s, tile->CrLen); /* CrLen (2 bytes) */
Stream_Write_UINT16(s, 0); /* tailLen (2 bytes) */
Stream_Write(s, tile->YData, tile->YLen); /* YData */
Stream_Write(s, tile->CbData, tile->CbLen); /* CbData */
Stream_Write(s, tile->CrData, tile->CrLen); /* CrData */
const RFX_TILE* tile = msg->tiles[i];
if (!progressive_write_tile_simple(progressive, s, tile))
return FALSE;
}
/* RFX_PROGRESSIVE_FRAME_END */
blockLen = 6;
if (!Stream_EnsureRemainingCapacity(s, blockLen))
{
if (!progressive_write_frame_end(progressive, s))
return FALSE;
}
Stream_Write_UINT16(s, 0xCCC2); /* blockType (2 bytes) */
Stream_Write_UINT32(s, blockLen); /* blockLen (4 bytes) */
return TRUE;
}
@ -2588,8 +2712,7 @@ int progressive_compress(PROGRESSIVE_CONTEXT* progressive, const BYTE* pSrcData,
return -2;
}
}
if (ScanLine / Width != 4)
return -3;
if (SrcSize < Height * ScanLine)
return -4;
@ -2609,13 +2732,16 @@ int progressive_compress(PROGRESSIVE_CONTEXT* progressive, const BYTE* pSrcData,
rects = (RFX_RECT*)Stream_Buffer(progressive->rects);
if (invalidRegion)
{
const RECTANGLE_16* r = region16_rects(invalidRegion, NULL);
const RECTANGLE_16* region_rects = region16_rects(invalidRegion, NULL);
for (x = 0; x < numRects; x++)
{
rects[x].x = r[x].left;
rects[x].y = r[x].top;
rects[x].width = r[x].right - r[x].left;
rects[x].height = r[x].bottom - r[x].top;
const RECTANGLE_16* r = &region_rects[x];
RFX_RECT* rect = &rects[x];
rect->x = r->left;
rect->y = r->top;
rect->width = r->right - r->left;
rect->height = r->bottom - r->top;
}
}
else
@ -2643,7 +2769,9 @@ int progressive_compress(PROGRESSIVE_CONTEXT* progressive, const BYTE* pSrcData,
Stream_SetPosition(s, 0);
progressive->rfx_context->mode = RLGR1;
progressive->rfx_context->width = Width;
progressive->rfx_context->height = Height;
rfx_context_set_pixel_format(progressive->rfx_context, SrcFormat);
message = rfx_encode_message(progressive->rfx_context, rects, numRects, pSrcData, Width, Height,
ScanLine);
if (!message)
@ -2654,14 +2782,14 @@ int progressive_compress(PROGRESSIVE_CONTEXT* progressive, const BYTE* pSrcData,
message->freeRects = TRUE;
rc = progressive_rfx_write_message_progressive_simple(progressive->rfx_context, s, message);
rc = progressive_rfx_write_message_progressive_simple(progressive, s, message);
rfx_message_free(progressive->rfx_context, message);
if (!rc)
goto fail;
*pDstSize = Stream_GetPosition(s);
*ppDstData = Stream_Buffer(s);
res = 0;
res = 1;
fail:
return res;
}
@ -2701,8 +2829,6 @@ PROGRESSIVE_CONTEXT* progressive_context_new(BOOL Compressor)
progressive->SurfaceContexts = HashTable_New(TRUE);
if (!progressive->SurfaceContexts)
goto fail;
if (!progressive_context_reset(progressive))
goto fail;
return progressive;
fail:

View File

@ -965,7 +965,52 @@ static BOOL shadow_client_send_surface_gfx(rdpShadowClient* client, const BYTE*
return FALSE;
}
}
else
{
INT32 rc;
REGION16 region;
RECTANGLE_16 regionRect;
if (shadow_encoder_prepare(encoder, FREERDP_CODEC_PROGRESSIVE) < 0)
{
WLog_ERR(TAG, "Failed to prepare encoder FREERDP_CODEC_PROGRESSIVE");
return FALSE;
}
WINPR_ASSERT(cmd.left <= UINT16_MAX);
WINPR_ASSERT(cmd.top <= UINT16_MAX);
WINPR_ASSERT(cmd.right <= UINT16_MAX);
WINPR_ASSERT(cmd.bottom <= UINT16_MAX);
regionRect.left = (UINT16)cmd.left;
regionRect.top = (UINT16)cmd.top;
regionRect.right = (UINT16)cmd.right;
regionRect.bottom = (UINT16)cmd.bottom;
region16_init(&region);
region16_union_rect(&region, &region, &regionRect);
rc = progressive_compress(encoder->progressive, pSrcData, nSrcStep * nHeight, cmd.format,
nWidth, nHeight, nSrcStep, &region, &cmd.data, &cmd.length);
region16_uninit(&region);
if (rc < 0)
{
WLog_ERR(TAG, "progressive_compress failed");
return FALSE;
}
/* rc > 0 means new data */
if (rc > 0)
{
cmd.codecId = RDPGFX_CODECID_CAPROGRESSIVE;
IFCALLRET(client->rdpgfx->SurfaceFrameCommand, error, client->rdpgfx, &cmd, &cmdstart,
&cmdend);
}
if (error)
{
WLog_ERR(TAG, "SurfaceFrameCommand failed with error %" PRIu32 "", error);
return FALSE;
}
}
return TRUE;
}
@ -1442,7 +1487,7 @@ static BOOL shadow_client_send_surface_update(rdpShadowClient* client, SHADOW_GF
// WLog_INFO(TAG, "shadow_client_send_surface_update: x: %d y: %d width: %d height: %d right: %d
// bottom: %d", nXSrc, nYSrc, nWidth, nHeight, nXSrc + nWidth, nYSrc + nHeight);
if (settings->SupportGraphicsPipeline && settings->GfxH264 && pStatus->gfxOpened)
if (settings->SupportGraphicsPipeline && pStatus->gfxOpened)
{
/* GFX/h264 always full screen encoded */
nWidth = settings->DesktopWidth;

View File

@ -20,6 +20,8 @@
#include "config.h"
#endif
#include <winpr/assert.h>
#include "shadow.h"
#include "shadow_encoder.h"
@ -252,6 +254,25 @@ fail:
return -1;
}
static int shadow_encoder_init_progressive(rdpShadowEncoder* encoder)
{
WINPR_ASSERT(encoder);
if (!encoder->progressive)
encoder->progressive = progressive_context_new(TRUE);
if (!encoder->progressive)
goto fail;
if (!progressive_context_reset(encoder->progressive))
goto fail;
encoder->codecs |= FREERDP_CODEC_PROGRESSIVE;
return 1;
fail:
progressive_context_free(encoder->progressive);
return -1;
}
static int shadow_encoder_init(rdpShadowEncoder* encoder)
{
encoder->width = encoder->server->screen->width;
@ -329,6 +350,19 @@ static int shadow_encoder_uninit_h264(rdpShadowEncoder* encoder)
return 1;
}
static int shadow_encoder_uninit_progressive(rdpShadowEncoder* encoder)
{
WINPR_ASSERT(encoder);
if (encoder->progressive)
{
progressive_context_free(encoder->progressive);
encoder->progressive = NULL;
}
encoder->codecs &= (UINT32)~FREERDP_CODEC_PROGRESSIVE;
return 1;
}
static int shadow_encoder_uninit(rdpShadowEncoder* encoder)
{
shadow_encoder_uninit_grid(encoder);
@ -339,32 +373,18 @@ static int shadow_encoder_uninit(rdpShadowEncoder* encoder)
encoder->bs = NULL;
}
if (encoder->codecs & FREERDP_CODEC_REMOTEFX)
{
shadow_encoder_uninit_rfx(encoder);
}
if (encoder->codecs & FREERDP_CODEC_NSCODEC)
{
shadow_encoder_uninit_nsc(encoder);
}
if (encoder->codecs & FREERDP_CODEC_PLANAR)
{
shadow_encoder_uninit_planar(encoder);
}
if (encoder->codecs & FREERDP_CODEC_INTERLEAVED)
{
shadow_encoder_uninit_interleaved(encoder);
}
if (encoder->codecs & (FREERDP_CODEC_AVC420 | FREERDP_CODEC_AVC444))
{
shadow_encoder_uninit_h264(encoder);
}
return 1;
shadow_encoder_uninit_progressive(encoder);
return 1;
}
int shadow_encoder_reset(rdpShadowEncoder* encoder)
@ -446,6 +466,15 @@ int shadow_encoder_prepare(rdpShadowEncoder* encoder, UINT32 codecs)
return -1;
}
if ((codecs & FREERDP_CODEC_PROGRESSIVE) && !(encoder->codecs & FREERDP_CODEC_PROGRESSIVE))
{
WLog_DBG(TAG, "initializing progressive encoder");
status = shadow_encoder_init_progressive(encoder);
if (status < 0)
return -1;
}
return 1;
}

View File

@ -50,6 +50,7 @@ struct rdp_shadow_encoder
BITMAP_PLANAR_CONTEXT* planar;
BITMAP_INTERLEAVED_CONTEXT* interleaved;
H264_CONTEXT* h264;
PROGRESSIVE_CONTEXT* progressive;
UINT32 fps;
UINT32 maxFps;