diff --git a/libfreerdp/codec/test/CMakeLists.txt b/libfreerdp/codec/test/CMakeLists.txt index 70eecb7a9..1334940aa 100644 --- a/libfreerdp/codec/test/CMakeLists.txt +++ b/libfreerdp/codec/test/CMakeLists.txt @@ -12,6 +12,7 @@ set(${MODULE_PREFIX}_TESTS TestFreeRDPCodecZGfx.c TestFreeRDPCodecPlanar.c TestFreeRDPCodecClear.c + TestFreeRDPCodecInterleaved.c TestFreeRDPCodecProgressive.c TestFreeRDPCodecRemoteFX.c) diff --git a/libfreerdp/codec/test/TestFreeRDPCodecInterleaved.c b/libfreerdp/codec/test/TestFreeRDPCodecInterleaved.c new file mode 100644 index 000000000..da7a10550 --- /dev/null +++ b/libfreerdp/codec/test/TestFreeRDPCodecInterleaved.c @@ -0,0 +1,152 @@ + +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif + +#include + +#include +#include + +#include +#include +#include +#include +#include +#include + +static BOOL run_encode_decode_single(UINT16 bpp, BITMAP_INTERLEAVED_CONTEXT* encoder, + BITMAP_INTERLEAVED_CONTEXT* decoder +#if defined(WITH_PROFILER) + , PROFILER* profiler_comp, PROFILER* profiler_decomp +#endif + ) +{ + BOOL rc2 = FALSE; + BOOL rc; + UINT32 i, j; + const UINT32 w = 64; + const UINT32 h = 64; + const UINT32 x = 0; + const UINT32 y = 0; + const UINT32 format = PIXEL_FORMAT_RGBX32; + const UINT32 bstep = GetBytesPerPixel(format); + const size_t step = (w + 13) * 4; + const size_t SrcSize = step * h; + const float maxDiff = 4.0f * ((bpp < 24) ? 2.0f : 1.0f); + UINT32 DstSize = SrcSize; + BYTE* pSrcData = malloc(SrcSize); + BYTE* pDstData = malloc(SrcSize); + BYTE* tmp = malloc(SrcSize); + + if (!pSrcData || !pDstData || !tmp) + goto fail; + + winpr_RAND(pSrcData, SrcSize); + + if (!bitmap_interleaved_context_reset(encoder) || !bitmap_interleaved_context_reset(decoder)) + goto fail; + + PROFILER_ENTER(profiler_comp); + rc = interleaved_compress(decoder, tmp, &DstSize, w, h, pSrcData, + format, step, x, y, NULL, bpp); + PROFILER_EXIT(profiler_comp); + + if (!rc) + goto fail; + + PROFILER_ENTER(profiler_decomp); + rc = interleaved_decompress(encoder, tmp, DstSize, w, h, bpp, pDstData, + format, step, x, y, w, h, NULL); + PROFILER_EXIT(profiler_decomp); + + if (!rc) + goto fail; + + for (i = 0; i < h; i++) + { + const BYTE* srcLine = &pSrcData[i * step]; + const BYTE* dstLine = &pDstData[i * step]; + + for (j = 0; j < w; j++) + { + BYTE r, g, b, dr, dg, db; + const UINT32 srcColor = ReadColor(&srcLine[j * bstep], format); + const UINT32 dstColor = ReadColor(&dstLine[j * bstep], format); + SplitColor(srcColor, format, &r, &g, &b, NULL, NULL); + SplitColor(dstColor, format, &dr, &dg, &db, NULL, NULL); + + if (fabsf((float)r - dr) > maxDiff) + goto fail; + + if (fabsf((float)g - dg) > maxDiff) + goto fail; + + if (fabsf((float)b - db) > maxDiff) + goto fail; + } + } + + rc2 = TRUE; +fail: + free(pSrcData); + free(pDstData); + free(tmp); + return rc2; +} + +static BOOL run_encode_decode(UINT16 bpp, BITMAP_INTERLEAVED_CONTEXT* encoder, + BITMAP_INTERLEAVED_CONTEXT* decoder) +{ + BOOL rc = FALSE; + UINT32 x; + PROFILER_DEFINE(profiler_comp); + PROFILER_DEFINE(profiler_decomp); + PROFILER_CREATE(profiler_comp, "interleaved_compress") + PROFILER_CREATE(profiler_decomp, "interleaved_decompress") + + for (x = 0; x < 100; x++) + { + if (!run_encode_decode_single(bpp, encoder, decoder +#if defined(WITH_PROFILER) + , profiler_comp, profiler_decomp +#endif + )) + goto fail; + } + + rc = TRUE; +fail: + PROFILER_PRINT_HEADER + PROFILER_PRINT(profiler_comp); + PROFILER_PRINT(profiler_decomp); + PROFILER_PRINT_FOOTER + PROFILER_FREE(profiler_comp); + PROFILER_FREE(profiler_decomp); + return rc; +} +int TestFreeRDPCodecInterleaved(int argc, char* argv[]) +{ + BITMAP_INTERLEAVED_CONTEXT* encoder, * decoder; + int rc = -1; + encoder = bitmap_interleaved_context_new(TRUE); + decoder = bitmap_interleaved_context_new(FALSE); + + if (!encoder || !decoder) + goto fail; + + if (!run_encode_decode(24, encoder, decoder)) + goto fail; + + if (!run_encode_decode(16, encoder, decoder)) + goto fail; + + if (!run_encode_decode(15, encoder, decoder)) + goto fail; + + rc = 0; +fail: + bitmap_interleaved_context_free(encoder); + bitmap_interleaved_context_free(decoder); + return rc; +}