2#include <freerdp/config.h>
7#include <winpr/print.h>
11#include <freerdp/freerdp.h>
12#include <freerdp/codec/color.h>
13#include <freerdp/codec/bitmap.h>
14#include <freerdp/codec/interleaved.h>
15#include <winpr/crypto.h>
16#include <freerdp/utils/profiler.h>
18#include "TestFreeRDPHelpers.h"
22static bool run_encode_decode_single(UINT16 bpp, BITMAP_INTERLEAVED_CONTEXT* encoder,
23 BITMAP_INTERLEAVED_CONTEXT* decoder
24#
if defined(WITH_PROFILER)
26 PROFILER* profiler_comp, PROFILER* profiler_decomp
36 const UINT32 format = PIXEL_FORMAT_RGBX32;
37 const UINT32 bstep = FreeRDPGetBytesPerPixel(format);
38 const size_t step = (13ULL + w) * 4ULL;
39 const size_t SrcSize = step * h;
40 const int maxDiff = 4 * ((bpp < 24) ? 2 : 1);
41 UINT32 DstSize = SrcSize;
42 BYTE* pSrcData = calloc(1, SrcSize);
43 BYTE* pDstData = calloc(1, SrcSize);
44 BYTE* tmp = calloc(1, SrcSize);
46 if (!pSrcData || !pDstData || !tmp)
49 if (winpr_RAND(pSrcData, SrcSize) < 0)
52 if (!bitmap_interleaved_context_reset(encoder) || !bitmap_interleaved_context_reset(decoder))
55 PROFILER_ENTER(profiler_comp)
56 rc = interleaved_compress(encoder, tmp, &DstSize, w, h, pSrcData, format, step, x, y,
nullptr,
58 PROFILER_EXIT(profiler_comp)
63 PROFILER_ENTER(profiler_decomp)
64 rc = interleaved_decompress(decoder, tmp, DstSize, w, h, bpp, pDstData, format, step, x, y, w,
66 PROFILER_EXIT(profiler_decomp)
71 for (UINT32 i = 0; i < h; i++)
73 const BYTE* srcLine = &pSrcData[i * step];
74 const BYTE* dstLine = &pDstData[i * step];
76 for (UINT32 j = 0; j < w; j++)
84 const UINT32 srcColor = FreeRDPReadColor(&srcLine[1ULL * j * bstep], format);
85 const UINT32 dstColor = FreeRDPReadColor(&dstLine[1ULL * j * bstep], format);
86 FreeRDPSplitColor(srcColor, format, &r, &g, &b,
nullptr,
nullptr);
87 FreeRDPSplitColor(dstColor, format, &dr, &dg, &db,
nullptr,
nullptr);
89 if (abs(r - dr) > maxDiff)
92 if (abs(g - dg) > maxDiff)
95 if (abs(b - db) > maxDiff)
108static const char* get_profiler_name(
bool encode, UINT16 bpp)
114 return "interleaved_compress 24bpp";
116 return "interleaved_decompress 24bpp";
120 return "interleaved_compress 16bpp";
122 return "interleaved_decompress 16bpp";
126 return "interleaved_compress 15bpp";
128 return "interleaved_decompress 15bpp";
131 return "configuration error!";
135static bool run_encode_decode(UINT16 bpp, BITMAP_INTERLEAVED_CONTEXT* encoder,
136 BITMAP_INTERLEAVED_CONTEXT* decoder)
139 PROFILER_DEFINE(profiler_comp)
140 PROFILER_DEFINE(profiler_decomp)
141 PROFILER_CREATE(profiler_comp, get_profiler_name(
true, bpp))
142 PROFILER_CREATE(profiler_decomp, get_profiler_name(
false, bpp))
144 for (UINT32 x = 0; x < 50; x++)
146 if (!run_encode_decode_single(bpp, encoder, decoder
147#
if defined(WITH_PROFILER)
149 profiler_comp, profiler_decomp
157 PROFILER_PRINT_HEADER
158 PROFILER_PRINT(profiler_comp)
159 PROFILER_PRINT(profiler_decomp)
160 PROFILER_PRINT_FOOTER
161 PROFILER_FREE(profiler_comp)
162 PROFILER_FREE(profiler_decomp)
166static bool TestColorConversion(
void)
168 const UINT32 formats[] = { PIXEL_FORMAT_RGB15, PIXEL_FORMAT_BGR15, PIXEL_FORMAT_ABGR15,
169 PIXEL_FORMAT_ARGB15, PIXEL_FORMAT_BGR16, PIXEL_FORMAT_RGB16 };
172 for (UINT32 x = 0; x < ARRAYSIZE(formats); x++)
174 const UINT32 dstFormat = PIXEL_FORMAT_RGBA32;
175 const UINT32 format = formats[x];
176 const UINT32 colorLow = FreeRDPGetColor(format, 0, 0, 0, 255);
177 const UINT32 colorHigh = FreeRDPGetColor(format, 255, 255, 255, 255);
178 const UINT32 colorLow32 = FreeRDPConvertColor(colorLow, format, dstFormat,
nullptr);
179 const UINT32 colorHigh32 = FreeRDPConvertColor(colorHigh, format, dstFormat,
nullptr);
184 FreeRDPSplitColor(colorLow32, dstFormat, &r, &g, &b, &a,
nullptr);
185 if ((r != 0) || (g != 0) || (b != 0))
188 FreeRDPSplitColor(colorHigh32, dstFormat, &r, &g, &b, &a,
nullptr);
189 if ((r != 255) || (g != 255) || (b != 255))
196static bool RunEncoderTest(
const char* name, uint32_t format, uint32_t width, uint32_t height,
197 uint32_t step, uint32_t bpp)
200 void* data =
nullptr;
201 void* encdata =
nullptr;
202 BITMAP_INTERLEAVED_CONTEXT* encoder = bitmap_interleaved_context_new(
true);
207 data = test_codec_helper_read_data(
"interleaved",
"bmp", name, &srclen);
211 encdata = calloc(srclen, 1);
215 for (
size_t x = 0; x < 42; x++)
217 uint32_t enclen = WINPR_ASSERTING_INT_CAST(uint32_t, srclen);
218 if (!interleaved_compress(encoder, encdata, &enclen, width, height, data, format, step, 0,
222 char encname[128] = WINPR_C_ARRAY_INIT;
223 (void)_snprintf(encname,
sizeof(encname),
"enc-%" PRIu32, bpp);
224#if defined(CREATE_TEST_OUTPUT)
225 test_codec_helper_write_data(
"interleaved", encname, name, encdata, enclen);
227 if (!test_codec_helper_compare(
"interleaved", encname, name, encdata, enclen))
237 bitmap_interleaved_context_free(encoder);
241static bool RunDecoderTest(
const char* name, uint32_t format, uint32_t width, uint32_t height,
242 uint32_t step, uint32_t bpp)
245 void* data =
nullptr;
246 void* decdata =
nullptr;
247 BITMAP_INTERLEAVED_CONTEXT* decoder = bitmap_interleaved_context_new(
false);
251 char encname[128] = WINPR_C_ARRAY_INIT;
252 (void)_snprintf(encname,
sizeof(encname),
"enc-%" PRIu32, bpp);
255 data = test_codec_helper_read_data(
"interleaved", encname, name, &srclen);
259 const size_t declen = 1ULL * step * height;
260 decdata = calloc(step, height);
264 for (
size_t x = 0; x < 42; x++)
266 if (!interleaved_decompress(decoder, data, WINPR_ASSERTING_INT_CAST(uint32_t, srclen),
267 width, height, bpp, decdata, format, step, 0, 0, width, height,
271 char decname[128] = WINPR_C_ARRAY_INIT;
272 (void)_snprintf(decname,
sizeof(decname),
"dec-%s", encname);
273#if defined(CREATE_TEST_OUTPUT)
274 test_codec_helper_write_data(
"interleaved", decname, name, decdata, declen);
276 if (!test_codec_helper_compare(
"interleaved", decname, name, decdata, declen))
286 bitmap_interleaved_context_free(decoder);
305static bool isObjectValid(
const WINPR_JSON* obj)
310 const char* strvalues[] = {
"name",
"format" };
311 for (
size_t x = 0; x < ARRAYSIZE(strvalues); x++)
313 const char* val = strvalues[x];
326 const char* values[] = {
"width",
"height",
"step" };
327 for (
size_t x = 0; x < ARRAYSIZE(values); x++)
329 const char* val = values[x];
343 const char* val =
"bpp";
365static bool TestEncoder(
void)
368 WINPR_JSON* json =
nullptr;
369 char* file =
nullptr;
370 char* path = GetCombinedPath(CMAKE_CURRENT_SOURCE_DIR,
"interleaved");
373 file = GetCombinedPath(path,
"encoder.json");
387 if (!isObjectValid(obj))
391 const uint32_t format = WINPR_ASSERTING_INT_CAST(
392 uint32_t, FreeRDPGetColorFromatFromName(
394 const uint32_t width = WINPR_ASSERTING_INT_CAST(
396 const uint32_t height = WINPR_ASSERTING_INT_CAST(
398 const uint32_t step = WINPR_ASSERTING_INT_CAST(
404 const uint32_t bpp = WINPR_ASSERTING_INT_CAST(
406 if (!RunEncoderTest(name, format, width, height, step, bpp))
408 if (!RunDecoderTest(name, format, width, height, step, bpp))
421int TestFreeRDPCodecInterleaved(
int argc,
char* argv[])
423 BITMAP_INTERLEAVED_CONTEXT* encoder =
nullptr;
424 BITMAP_INTERLEAVED_CONTEXT* decoder =
nullptr;
428 encoder = bitmap_interleaved_context_new(
true);
429 decoder = bitmap_interleaved_context_new(
false);
431 if (!encoder || !decoder)
434 if (!run_encode_decode(24, encoder, decoder))
437 if (!run_encode_decode(16, encoder, decoder))
440 if (!run_encode_decode(15, encoder, decoder))
443 if (!TestColorConversion())
451 bitmap_interleaved_context_free(encoder);
452 bitmap_interleaved_context_free(decoder);
WINPR_API BOOL WINPR_JSON_HasObjectItem(const WINPR_JSON *object, const char *string)
Check if JSON has an object matching the name.
WINPR_API WINPR_JSON * WINPR_JSON_GetObjectItem(const WINPR_JSON *object, const char *string)
Return a pointer to an JSON object item.
WINPR_API BOOL WINPR_JSON_IsString(const WINPR_JSON *item)
Check if JSON item is of type String.
WINPR_API double WINPR_JSON_GetNumberValue(const WINPR_JSON *item)
Return the Number value of a JSON item.
WINPR_ATTR_NODISCARD WINPR_API WINPR_JSON * WINPR_JSON_ParseFromFile(const char *filename)
Parse a JSON string read from a file filename.
WINPR_API BOOL WINPR_JSON_IsNumber(const WINPR_JSON *item)
Check if JSON item is of type Number.
WINPR_API WINPR_JSON * WINPR_JSON_GetArrayItem(const WINPR_JSON *array, size_t index)
Return a pointer to an item in the array.
WINPR_API BOOL WINPR_JSON_IsObject(const WINPR_JSON *item)
Check if JSON item is of type Object.
WINPR_API const char * WINPR_JSON_GetStringValue(WINPR_JSON *item)
Return the String value of a JSON item.
WINPR_API void WINPR_JSON_Delete(WINPR_JSON *item)
Delete a WinPR JSON wrapper object.
WINPR_API size_t WINPR_JSON_GetArraySize(const WINPR_JSON *array)
Get the number of arrayitems from an array.
WINPR_API BOOL WINPR_JSON_IsArray(const WINPR_JSON *item)
Check if JSON item is of type Array.