diff --git a/include/freerdp/codec/planar.h b/include/freerdp/codec/planar.h index fc51f44ec..ba58b08f3 100644 --- a/include/freerdp/codec/planar.h +++ b/include/freerdp/codec/planar.h @@ -25,6 +25,7 @@ #include #include +#include #include #include @@ -38,20 +39,6 @@ extern "C" { #endif - static inline BYTE PLANAR_CONTROL_BYTE(UINT32 nRunLength, UINT32 cRawBytes) - { - return WINPR_ASSERTING_INT_CAST(UINT8, ((nRunLength & 0x0F) | ((cRawBytes & 0x0F) << 4))); - } - - static inline BYTE PLANAR_CONTROL_BYTE_RUN_LENGTH(UINT32 controlByte) - { - return (controlByte & 0x0F); - } - static inline BYTE PLANAR_CONTROL_BYTE_RAW_BYTES(UINT32 controlByte) - { - return ((controlByte >> 4) & 0x0F); - } - typedef struct S_BITMAP_PLANAR_CONTEXT BITMAP_PLANAR_CONTEXT; FREERDP_API BYTE* freerdp_bitmap_compress_planar(BITMAP_PLANAR_CONTEXT* WINPR_RESTRICT context, @@ -74,12 +61,21 @@ extern "C" FREERDP_API void freerdp_planar_topdown_image(BITMAP_PLANAR_CONTEXT* WINPR_RESTRICT planar, BOOL topdown); - FREERDP_API BOOL planar_decompress(BITMAP_PLANAR_CONTEXT* WINPR_RESTRICT planar, - const BYTE* WINPR_RESTRICT pSrcData, UINT32 SrcSize, - UINT32 nSrcWidth, UINT32 nSrcHeight, - BYTE* WINPR_RESTRICT pDstData, UINT32 DstFormat, - UINT32 nDstStep, UINT32 nXDst, UINT32 nYDst, - UINT32 nDstWidth, UINT32 nDstHeight, BOOL vFlip); +#if !defined(WITHOUT_FREERDP_3x_DEPRECATED) + WINPR_DEPRECATED_VAR("use freerdp_bitmap_decompress_planar instead", + FREERDP_API BOOL planar_decompress( + BITMAP_PLANAR_CONTEXT* WINPR_RESTRICT planar, + const BYTE* WINPR_RESTRICT pSrcData, UINT32 SrcSize, UINT32 nSrcWidth, + UINT32 nSrcHeight, BYTE* WINPR_RESTRICT pDstData, UINT32 DstFormat, + UINT32 nDstStep, UINT32 nXDst, UINT32 nYDst, UINT32 nDstWidth, + UINT32 nDstHeight, BOOL vFlip)); +#endif + + FREERDP_API BOOL freerdp_bitmap_decompress_planar( + BITMAP_PLANAR_CONTEXT* WINPR_RESTRICT planar, const BYTE* WINPR_RESTRICT pSrcData, + UINT32 SrcSize, UINT32 nSrcWidth, UINT32 nSrcHeight, BYTE* WINPR_RESTRICT pDstData, + UINT32 DstFormat, UINT32 nDstStep, UINT32 nXDst, UINT32 nYDst, UINT32 nDstWidth, + UINT32 nDstHeight, BOOL vFlip); #ifdef __cplusplus } diff --git a/libfreerdp/codec/planar.c b/libfreerdp/codec/planar.c index 4092686dc..9d4cf078c 100644 --- a/libfreerdp/codec/planar.c +++ b/libfreerdp/codec/planar.c @@ -96,10 +96,24 @@ struct S_BITMAP_PLANAR_CONTEXT BOOL topdown; }; +static inline BYTE PLANAR_CONTROL_BYTE(UINT32 nRunLength, UINT32 cRawBytes) +{ + return WINPR_ASSERTING_INT_CAST(UINT8, ((nRunLength & 0x0F) | ((cRawBytes & 0x0F) << 4))); +} + +static inline BYTE PLANAR_CONTROL_BYTE_RUN_LENGTH(UINT32 controlByte) +{ + return (controlByte & 0x0F); +} +static inline BYTE PLANAR_CONTROL_BYTE_RAW_BYTES(UINT32 controlByte) +{ + return ((controlByte >> 4) & 0x0F); +} + static INLINE UINT32 planar_invert_format(BITMAP_PLANAR_CONTEXT* WINPR_RESTRICT planar, BOOL alpha, UINT32 DstFormat) { - + WINPR_ASSERT(planar); if (planar->bgr && alpha) { switch (DstFormat) @@ -361,8 +375,6 @@ static INLINE INT32 planar_decompress_plane_rle(const BYTE* WINPR_RESTRICT pSrcD WINPR_ASSERT(nWidth <= INT32_MAX); WINPR_ASSERT(nDstStep <= INT32_MAX); - previousScanline = NULL; - if (vFlip) { beg = (INT32)nHeight - 1; @@ -486,8 +498,8 @@ static INLINE INT32 planar_set_plane(BYTE bValue, BYTE* pDstData, UINT32 nDstSte BOOL vFlip) { INT32 beg = 0; - INT32 end = 0; - INT32 inc = 0; + INT32 end = (INT32)nHeight; + INT32 inc = 1; WINPR_ASSERT(nHeight <= INT32_MAX); WINPR_ASSERT(nWidth <= INT32_MAX); @@ -499,12 +511,6 @@ static INLINE INT32 planar_set_plane(BYTE bValue, BYTE* pDstData, UINT32 nDstSte end = -1; inc = -1; } - else - { - beg = 0; - end = (INT32)nHeight; - inc = 1; - } for (INT32 y = beg; y != end; y += inc) { @@ -687,11 +693,25 @@ static BOOL planar_subsample_expand(const BYTE* WINPR_RESTRICT plane, size_t pla return TRUE; } +#if !defined(WITHOUT_FREERDP_3x_DEPRECATED) BOOL planar_decompress(BITMAP_PLANAR_CONTEXT* WINPR_RESTRICT planar, const BYTE* WINPR_RESTRICT pSrcData, UINT32 SrcSize, UINT32 nSrcWidth, UINT32 nSrcHeight, BYTE* WINPR_RESTRICT pDstData, UINT32 DstFormat, UINT32 nDstStep, UINT32 nXDst, UINT32 nYDst, UINT32 nDstWidth, UINT32 nDstHeight, BOOL vFlip) +{ + return freerdp_bitmap_decompress_planar(planar, pSrcData, SrcSize, nSrcWidth, nSrcHeight, + pDstData, DstFormat, nDstStep, nXDst, nYDst, nDstWidth, + nDstHeight, vFlip); +} +#endif + +BOOL freerdp_bitmap_decompress_planar(BITMAP_PLANAR_CONTEXT* WINPR_RESTRICT planar, + const BYTE* WINPR_RESTRICT pSrcData, UINT32 SrcSize, + UINT32 nSrcWidth, UINT32 nSrcHeight, + BYTE* WINPR_RESTRICT pDstData, UINT32 DstFormat, + UINT32 nDstStep, UINT32 nXDst, UINT32 nYDst, UINT32 nDstWidth, + UINT32 nDstHeight, BOOL vFlip) { BOOL useAlpha = FALSE; INT32 status = 0; @@ -1155,12 +1175,10 @@ static INLINE UINT32 freerdp_bitmap_planar_write_rle_bytes(const BYTE* WINPR_RES BYTE* WINPR_RESTRICT pOutBuffer, UINT32 outBufferSize) { - const BYTE* pInput = NULL; - BYTE* pOutput = NULL; + const BYTE* pInput = pInBuffer; + BYTE* pOutput = pOutBuffer; BYTE controlByte = 0; UINT32 nBytesToWrite = 0; - pInput = pInBuffer; - pOutput = pOutBuffer; if (!cRawBytes && !nRunLength) return 0; @@ -1274,20 +1292,13 @@ static INLINE UINT32 freerdp_bitmap_planar_encode_rle_bytes(const BYTE* WINPR_RE UINT32 outBufferSize) { BYTE symbol = 0; - const BYTE* pInput = NULL; - BYTE* pOutput = NULL; + const BYTE* pInput = pInBuffer; + BYTE* pOutput = pOutBuffer; const BYTE* pBytes = NULL; UINT32 cRawBytes = 0; UINT32 nRunLength = 0; - UINT32 bSymbolMatch = 0; UINT32 nBytesWritten = 0; UINT32 nTotalBytesWritten = 0; - symbol = 0; - cRawBytes = 0; - nRunLength = 0; - pInput = pInBuffer; - pOutput = pOutBuffer; - nTotalBytesWritten = 0; if (!outBufferSize) return 0; @@ -1297,7 +1308,7 @@ static INLINE UINT32 freerdp_bitmap_planar_encode_rle_bytes(const BYTE* WINPR_RE if (!inBufferSize) break; - bSymbolMatch = (symbol == *pInput) ? TRUE : FALSE; + const UINT32 bSymbolMatch = (symbol == *pInput) ? TRUE : FALSE; symbol = *pInput; pInput++; inBufferSize--; @@ -1352,25 +1363,18 @@ BOOL freerdp_bitmap_planar_compress_plane_rle(const BYTE* WINPR_RESTRICT inPlane UINT32 height, BYTE* WINPR_RESTRICT outPlane, UINT32* WINPR_RESTRICT dstSize) { - UINT32 index = 0; - const BYTE* pInput = NULL; - BYTE* pOutput = NULL; - UINT32 outBufferSize = 0; - UINT32 nBytesWritten = 0; - UINT32 nTotalBytesWritten = 0; - if (!outPlane) return FALSE; - index = 0; - pInput = inPlane; - pOutput = outPlane; - outBufferSize = *dstSize; - nTotalBytesWritten = 0; + UINT32 index = 0; + const BYTE* pInput = inPlane; + BYTE* pOutput = outPlane; + UINT32 outBufferSize = *dstSize; + UINT32 nTotalBytesWritten = 0; - while (outBufferSize) + while (outBufferSize > 0) { - nBytesWritten = + const UINT32 nBytesWritten = freerdp_bitmap_planar_encode_rle_bytes(pInput, width, pOutput, outBufferSize); if ((!nBytesWritten) || (nBytesWritten > outBufferSize)) @@ -1446,35 +1450,33 @@ static INLINE BOOL freerdp_bitmap_planar_compress_planes_rle(BYTE* WINPR_RESTRIC BYTE* freerdp_bitmap_planar_delta_encode_plane(const BYTE* WINPR_RESTRICT inPlane, UINT32 width, UINT32 height, BYTE* WINPR_RESTRICT outPlane) { - BYTE* outPtr = NULL; - const BYTE* srcPtr = NULL; - const BYTE* prevLinePtr = NULL; - if (!outPlane) { if (width * height == 0) return NULL; - if (!(outPlane = (BYTE*)calloc(height, width))) + outPlane = (BYTE*)calloc(height, width); + if (!outPlane) return NULL; } // first line is copied as is CopyMemory(outPlane, inPlane, width); - outPtr = outPlane + width; - srcPtr = inPlane + width; - prevLinePtr = inPlane; for (UINT32 y = 1; y < height; y++) { - for (UINT32 x = 0; x < width; x++, outPtr++, srcPtr++, prevLinePtr++) + const size_t off = 1ull * width * y; + BYTE* outPtr = &outPlane[off]; + const BYTE* srcPtr = &inPlane[off]; + const BYTE* prevLinePtr = &inPlane[off - width]; + for (UINT32 x = 0; x < width; x++) { - const INT32 delta = *srcPtr - *prevLinePtr; - const int s2c1i = (delta >= 0) ? delta : (~((BYTE)(-delta)) + 1); - const char s2c1 = WINPR_CXX_COMPAT_CAST(char, s2c1i & 0xff); - const uint32_t s2c = (s2c1 >= 0) ? ((UINT32)s2c1 << 1) - : (((UINT32)(~((BYTE)(s2c1 & 0xFF)) + 1) << 1) - 1); - *outPtr = (BYTE)s2c; + const int delta = (int)srcPtr[x] - (int)prevLinePtr[x]; + const int s2c1i = (delta >= 0) ? delta : (INT_MAX + delta) + 1; + const int8_t s2c1 = WINPR_CXX_COMPAT_CAST(int8_t, s2c1i); + const uint32_t s2c = + (s2c1 >= 0) ? ((UINT32)s2c1 << 1) : (((UINT32)(~(s2c1) + 1) << 1) - 1); + outPtr[x] = (BYTE)s2c; } } @@ -1504,7 +1506,6 @@ BYTE* freerdp_bitmap_compress_planar(BITMAP_PLANAR_CONTEXT* WINPR_RESTRICT conte { UINT32 size = 0; BYTE* dstp = NULL; - UINT32 planeSize = 0; UINT32 dstSizes[4] = { 0 }; BYTE FormatHeader = 0; @@ -1514,7 +1515,7 @@ BYTE* freerdp_bitmap_compress_planar(BITMAP_PLANAR_CONTEXT* WINPR_RESTRICT conte if (context->AllowSkipAlpha) FormatHeader |= PLANAR_FORMAT_HEADER_NA; - planeSize = width * height; + const UINT32 planeSize = width * height; if (!context->AllowSkipAlpha) format = planar_invert_format(context, TRUE, format); diff --git a/libfreerdp/codec/test/TestFreeRDPCodecPlanar.c b/libfreerdp/codec/test/TestFreeRDPCodecPlanar.c index 81d4ce484..5e8c02f01 100644 --- a/libfreerdp/codec/test/TestFreeRDPCodecPlanar.c +++ b/libfreerdp/codec/test/TestFreeRDPCodecPlanar.c @@ -171,7 +171,7 @@ static void* read_data(const char* type, const char* name, size_t* plength) cmp = NULL; fail: - (void)printf("%s: %s %s -> %p\n", __func__, type, name, cmp); + (void)printf("%s: %s %s -> %p\n", __func__, type, name, rc); free(cmp); if (fp) (void)fclose(fp); @@ -199,9 +199,18 @@ static BOOL compare(const char* type, const char* name, const void* data, size_t if (!cmp) goto fail; if (cmplen != length) + { + (void)printf("%s: %s %s: length mismatch: %" PRIuz " vs %" PRIuz "\n", __func__, type, name, + cmplen, length); goto fail; + } if (memcmp(data, cmp, length) != 0) + { + (void)printf("%s: %s %s: data mismatch\n", __func__, type, name); + winpr_HexDump(__func__, WLOG_WARN, data, length); + winpr_HexDump(__func__, WLOG_WARN, cmp, cmplen); goto fail; + } rc = TRUE; fail: (void)printf("%s: %s %s -> %s\n", __func__, type, name, rc ? "SUCCESS" : "FAILED"); @@ -228,10 +237,6 @@ static BOOL RunTestPlanar(BITMAP_PLANAR_CONTEXT* encplanar, BITMAP_PLANAR_CONTEX BYTE* decompressedBitmap = (BYTE*)calloc(height, 1ULL * width * FreeRDPGetBytesPerPixel(dstFormat)); - if (!compare("bmp", name, srcBitmap, - 1ull * width * height * FreeRDPGetBytesPerPixel(srcFormat))) - goto fail; - if (!compare("enc", name, compressedBitmap, dstSize)) goto fail; @@ -241,8 +246,9 @@ static BOOL RunTestPlanar(BITMAP_PLANAR_CONTEXT* encplanar, BITMAP_PLANAR_CONTEX if (!compressedBitmap || !decompressedBitmap) goto fail; - if (!planar_decompress(decplanar, compressedBitmap, dstSize, width, height, decompressedBitmap, - dstFormat, 0, 0, 0, width, height, FALSE)) + if (!freerdp_bitmap_decompress_planar(decplanar, compressedBitmap, dstSize, width, height, + decompressedBitmap, dstFormat, 0, 0, 0, width, height, + FALSE)) { (void)printf("failed to decompress experimental bitmap 01: width: %" PRIu32 " height: %" PRIu32 "\n", @@ -321,8 +327,9 @@ static BOOL RunTestPlanarSingleColor(BITMAP_PLANAR_CONTEXT* planar, const UINT32 if (!compressedBitmap) goto fail_loop; - if (!planar_decompress(planar, compressedBitmap, compressedSize, width, height, - decompressedBitmap, dstFormat, 0, 0, 0, width, height, FALSE)) + if (!freerdp_bitmap_decompress_planar(planar, compressedBitmap, compressedSize, width, + height, decompressedBitmap, dstFormat, 0, 0, 0, + width, height, FALSE)) goto fail_loop; if (!CompareBitmap(decompressedBitmap, dstFormat, bmp, srcFormat, width, height)) @@ -494,9 +501,9 @@ static BOOL FuzzPlanar(void) FreeRDPGetColorFormatName(DstFormat), nXDst, nYDst, nDstWidth, nDstHeight, nDstStep, sizeof(dstData)); freerdp_planar_switch_bgr(planar, ((prand(2) % 2) != 0) ? TRUE : FALSE); - planar_decompress(planar, data, dataSize, prand(4096), prand(4096), dstData, DstFormat, - nDstStep, nXDst, nYDst, nDstWidth, nDstHeight, - ((prand(2) % 2) != 0) ? TRUE : FALSE); + freerdp_bitmap_decompress_planar(planar, data, dataSize, prand(4096), prand(4096), dstData, + DstFormat, nDstStep, nXDst, nYDst, nDstWidth, nDstHeight, + ((prand(2) % 2) != 0) ? TRUE : FALSE); } rc = TRUE; diff --git a/libfreerdp/codec/test/TestFreeRDPCodecProgressive.c b/libfreerdp/codec/test/TestFreeRDPCodecProgressive.c index 89492ce64..60f22bdbe 100644 --- a/libfreerdp/codec/test/TestFreeRDPCodecProgressive.c +++ b/libfreerdp/codec/test/TestFreeRDPCodecProgressive.c @@ -1324,9 +1324,9 @@ static int test_dump(int argc, char* argv[]) { const UINT64 start = winpr_GetTickCount64NS(); - if (!planar_decompress(codecs->planar, cmd.data, cmd.length, cmd.width, - cmd.height, dst, DstFormat, stride, cmd.left, cmd.top, - cmd.width, cmd.height, FALSE)) + if (!freerdp_bitmap_decompress_planar( + codecs->planar, cmd.data, cmd.length, cmd.width, cmd.height, dst, + DstFormat, stride, cmd.left, cmd.top, cmd.width, cmd.height, FALSE)) success = -1; const RECTANGLE_16 invalidRect = { .left = (UINT16)MIN(UINT16_MAX, cmd.left), diff --git a/libfreerdp/gdi/gfx.c b/libfreerdp/gdi/gfx.c index 4a0a2ede8..13deae0cd 100644 --- a/libfreerdp/gdi/gfx.c +++ b/libfreerdp/gdi/gfx.c @@ -540,9 +540,10 @@ static UINT gdi_SurfaceCommand_Planar(rdpGdi* gdi, RdpgfxClientContext* context, if (!is_within_surface(surface, cmd)) return ERROR_INVALID_DATA; - if (!planar_decompress(surface->codecs->planar, cmd->data, cmd->length, cmd->width, cmd->height, - DstData, surface->format, surface->scanline, cmd->left, cmd->top, - cmd->width, cmd->height, FALSE)) + if (!freerdp_bitmap_decompress_planar(surface->codecs->planar, cmd->data, cmd->length, + cmd->width, cmd->height, DstData, surface->format, + surface->scanline, cmd->left, cmd->top, cmd->width, + cmd->height, FALSE)) return ERROR_INTERNAL_ERROR; invalidRect.left = (UINT16)MIN(UINT16_MAX, cmd->left); diff --git a/libfreerdp/gdi/graphics.c b/libfreerdp/gdi/graphics.c index 889eb95a1..2f616148c 100644 --- a/libfreerdp/gdi/graphics.c +++ b/libfreerdp/gdi/graphics.c @@ -206,11 +206,11 @@ static BOOL gdi_Bitmap_Decompress(rdpContext* context, rdpBitmap* bitmap, const const BOOL fidelity = freerdp_settings_get_bool(context->settings, FreeRDP_DrawAllowDynamicColorFidelity); freerdp_planar_switch_bgr(context->codecs->planar, fidelity); - if (!planar_decompress(context->codecs->planar, pSrcData, SrcSize, DstWidth, DstHeight, - bitmap->data, bitmap->format, 0, 0, 0, DstWidth, DstHeight, - TRUE)) + if (!freerdp_bitmap_decompress_planar(context->codecs->planar, pSrcData, SrcSize, + DstWidth, DstHeight, bitmap->data, bitmap->format, + 0, 0, 0, DstWidth, DstHeight, TRUE)) { - WLog_ERR(TAG, "planar_decompress failed"); + WLog_ERR(TAG, "freerdp_bitmap_decompress_planar failed"); return FALSE; } }