Added option to allow planar topdown encoding.

This commit is contained in:
akallabeth 2021-07-02 08:49:07 +02:00 committed by akallabeth
parent 77a7e4010f
commit 2ac12c558a
3 changed files with 52 additions and 29 deletions

View File

@ -99,6 +99,7 @@ struct _BITMAP_PLANAR_CONTEXT
UINT32 nTempStep;
BOOL bgr;
BOOL topdown;
};
#ifdef __cplusplus
@ -119,6 +120,7 @@ extern "C"
FREERDP_API void freerdp_bitmap_planar_context_free(BITMAP_PLANAR_CONTEXT* context);
FREERDP_API void freerdp_planar_switch_bgr(BITMAP_PLANAR_CONTEXT* planar, BOOL bgr);
FREERDP_API void freerdp_planar_topdown_image(BITMAP_PLANAR_CONTEXT* planar, BOOL topdown);
FREERDP_API BOOL planar_decompress(BITMAP_PLANAR_CONTEXT* planar, const BYTE* pSrcData,
UINT32 SrcSize, UINT32 nSrcWidth, UINT32 nSrcHeight,

View File

@ -24,6 +24,7 @@
#endif
#include <winpr/crt.h>
#include <winpr/assert.h>
#include <winpr/print.h>
#include <freerdp/primitives.h>
@ -940,32 +941,54 @@ BOOL planar_decompress(BITMAP_PLANAR_CONTEXT* planar, const BYTE* pSrcData, UINT
return TRUE;
}
static INLINE BOOL freerdp_split_color_planes(const BYTE* data, UINT32 format, UINT32 width,
UINT32 height, UINT32 scanline, BYTE* planes[4])
static INLINE BOOL freerdp_split_color_planes(BITMAP_PLANAR_CONTEXT* planar, const BYTE* data,
UINT32 format, UINT32 width, UINT32 height,
UINT32 scanline, BYTE* planes[4])
{
INT64 i, j, k;
WINPR_ASSERT(planar);
if ((width > INT32_MAX) || (height > INT32_MAX) || (scanline > INT32_MAX))
return FALSE;
k = 0;
if (scanline == 0)
scanline = width * GetBytesPerPixel(format);
for (i = (INT64)height - 1; i >= 0; i--)
if (planar->topdown)
{
const BYTE* pixel = &data[scanline * (UINT32)i];
for (j = 0; j < (INT64)width; j++)
UINT32 i, j, k = 0;
for (i = 0; i < height; i++)
{
const UINT32 color = ReadColor(pixel, format);
pixel += GetBytesPerPixel(format);
SplitColor(color, format, &planes[1][k], &planes[2][k], &planes[3][k], &planes[0][k],
NULL);
k++;
const BYTE* pixel = &data[scanline * (UINT32)i];
for (j = 0; j < width; j++)
{
const UINT32 color = ReadColor(pixel, format);
pixel += GetBytesPerPixel(format);
SplitColor(color, format, &planes[1][k], &planes[2][k], &planes[3][k],
&planes[0][k], NULL);
k++;
}
}
}
else
{
INT64 i;
UINT32 j, k = 0;
for (i = (INT64)height - 1; i >= 0; i--)
{
const BYTE* pixel = &data[scanline * (UINT32)i];
for (j = 0; j < width; j++)
{
const UINT32 color = ReadColor(pixel, format);
pixel += GetBytesPerPixel(format);
SplitColor(color, format, &planes[1][k], &planes[2][k], &planes[3][k],
&planes[0][k], NULL);
k++;
}
}
}
return TRUE;
}
@ -1330,7 +1353,8 @@ BYTE* freerdp_bitmap_compress_planar(BITMAP_PLANAR_CONTEXT* context, const BYTE*
if (!context->AllowSkipAlpha)
format = planar_invert_format(context, TRUE, format);
if (!freerdp_split_color_planes(data, format, width, height, scanline, context->planes))
if (!freerdp_split_color_planes(context, data, format, width, height, scanline,
context->planes))
return NULL;
if (context->AllowRunLengthEncoding)
@ -1560,5 +1584,12 @@ void freerdp_bitmap_planar_context_free(BITMAP_PLANAR_CONTEXT* context)
void freerdp_planar_switch_bgr(BITMAP_PLANAR_CONTEXT* planar, BOOL bgr)
{
WINPR_ASSERT(planar);
planar->bgr = bgr;
}
void freerdp_planar_topdown_image(BITMAP_PLANAR_CONTEXT* planar, BOOL topdown)
{
WINPR_ASSERT(planar);
planar->topdown = topdown;
}

View File

@ -1246,10 +1246,7 @@ static BOOL shadow_client_send_surface_gfx(rdpShadowClient* client, const BYTE*
BOOL rc;
const UINT32 w = cmd.right - cmd.left;
const UINT32 h = cmd.bottom - cmd.top;
const size_t step = w * GetBytesPerPixel(SrcFormat);
const size_t size = step * h;
BYTE* dst;
const BYTE* src = &pSrcData[cmd.top * nSrcStep + cmd.left * GetBytesPerPixel(SrcFormat)];
if (shadow_encoder_prepare(encoder, FREERDP_CODEC_PLANAR) < 0)
{
WLog_ERR(TAG, "Failed to prepare encoder FREERDP_CODEC_PLANAR");
@ -1258,19 +1255,12 @@ static BOOL shadow_client_send_surface_gfx(rdpShadowClient* client, const BYTE*
rc = freerdp_bitmap_planar_context_reset(encoder->planar, w, h);
WINPR_ASSERT(rc);
freerdp_planar_topdown_image(encoder->planar, TRUE);
dst = malloc(size);
WINPR_ASSERT(dst);
rc = freerdp_image_copy(dst, SrcFormat, step, 0, 0, w, h, pSrcData, SrcFormat, nSrcStep,
cmd.left, cmd.top, NULL, FREERDP_FLIP_VERTICAL);
WINPR_ASSERT(rc);
cmd.data = freerdp_bitmap_compress_planar(encoder->planar, dst, SrcFormat, w, h, step, NULL,
&cmd.length);
cmd.data = freerdp_bitmap_compress_planar(encoder->planar, src, SrcFormat, w, h, nSrcStep,
NULL, &cmd.length);
WINPR_ASSERT(cmd.data || (cmd.length == 0));
free(dst);
cmd.codecId = RDPGFX_CODECID_PLANAR;
IFCALLRET(client->rdpgfx->SurfaceFrameCommand, error, client->rdpgfx, &cmd, &cmdstart,