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 winpr_RAND(pSrcData, SrcSize);
51 if (!bitmap_interleaved_context_reset(encoder) || !bitmap_interleaved_context_reset(decoder))
54 PROFILER_ENTER(profiler_comp)
56 interleaved_compress(encoder, tmp, &DstSize, w, h, pSrcData, format, step, x, y, NULL, bpp);
57 PROFILER_EXIT(profiler_comp)
62 PROFILER_ENTER(profiler_decomp)
63 rc = interleaved_decompress(decoder, tmp, DstSize, w, h, bpp, pDstData, format, step, x, y, w,
65 PROFILER_EXIT(profiler_decomp)
70 for (UINT32 i = 0; i < h; i++)
72 const BYTE* srcLine = &pSrcData[i * step];
73 const BYTE* dstLine = &pDstData[i * step];
75 for (UINT32 j = 0; j < w; j++)
83 const UINT32 srcColor = FreeRDPReadColor(&srcLine[1ULL * j * bstep], format);
84 const UINT32 dstColor = FreeRDPReadColor(&dstLine[1ULL * j * bstep], format);
85 FreeRDPSplitColor(srcColor, format, &r, &g, &b, NULL, NULL);
86 FreeRDPSplitColor(dstColor, format, &dr, &dg, &db, NULL, NULL);
88 if (abs(r - dr) > maxDiff)
91 if (abs(g - dg) > maxDiff)
94 if (abs(b - db) > maxDiff)
107static const char* get_profiler_name(
bool encode, UINT16 bpp)
113 return "interleaved_compress 24bpp";
115 return "interleaved_decompress 24bpp";
119 return "interleaved_compress 16bpp";
121 return "interleaved_decompress 16bpp";
125 return "interleaved_compress 15bpp";
127 return "interleaved_decompress 15bpp";
130 return "configuration error!";
134static bool run_encode_decode(UINT16 bpp, BITMAP_INTERLEAVED_CONTEXT* encoder,
135 BITMAP_INTERLEAVED_CONTEXT* decoder)
138 PROFILER_DEFINE(profiler_comp)
139 PROFILER_DEFINE(profiler_decomp)
140 PROFILER_CREATE(profiler_comp, get_profiler_name(
true, bpp))
141 PROFILER_CREATE(profiler_decomp, get_profiler_name(
false, bpp))
143 for (UINT32 x = 0; x < 50; x++)
145 if (!run_encode_decode_single(bpp, encoder, decoder
146#
if defined(WITH_PROFILER)
148 profiler_comp, profiler_decomp
156 PROFILER_PRINT_HEADER
157 PROFILER_PRINT(profiler_comp)
158 PROFILER_PRINT(profiler_decomp)
159 PROFILER_PRINT_FOOTER
160 PROFILER_FREE(profiler_comp)
161 PROFILER_FREE(profiler_decomp)
165static bool TestColorConversion(
void)
167 const UINT32 formats[] = { PIXEL_FORMAT_RGB15, PIXEL_FORMAT_BGR15, PIXEL_FORMAT_ABGR15,
168 PIXEL_FORMAT_ARGB15, PIXEL_FORMAT_BGR16, PIXEL_FORMAT_RGB16 };
171 for (UINT32 x = 0; x < ARRAYSIZE(formats); x++)
173 const UINT32 dstFormat = PIXEL_FORMAT_RGBA32;
174 const UINT32 format = formats[x];
175 const UINT32 colorLow = FreeRDPGetColor(format, 0, 0, 0, 255);
176 const UINT32 colorHigh = FreeRDPGetColor(format, 255, 255, 255, 255);
177 const UINT32 colorLow32 = FreeRDPConvertColor(colorLow, format, dstFormat, NULL);
178 const UINT32 colorHigh32 = FreeRDPConvertColor(colorHigh, format, dstFormat, NULL);
183 FreeRDPSplitColor(colorLow32, dstFormat, &r, &g, &b, &a, NULL);
184 if ((r != 0) || (g != 0) || (b != 0))
187 FreeRDPSplitColor(colorHigh32, dstFormat, &r, &g, &b, &a, NULL);
188 if ((r != 255) || (g != 255) || (b != 255))
195static bool RunEncoderTest(
const char* name, uint32_t format, uint32_t width, uint32_t height,
196 uint32_t step, uint32_t bpp)
200 void* encdata = NULL;
201 BITMAP_INTERLEAVED_CONTEXT* encoder = bitmap_interleaved_context_new(
true);
206 data = test_codec_helper_read_data(
"interleaved",
"bmp", name, &srclen);
210 encdata = calloc(srclen, 1);
214 for (
size_t x = 0; x < 42; x++)
216 uint32_t enclen = WINPR_ASSERTING_INT_CAST(uint32_t, srclen);
217 if (!interleaved_compress(encoder, encdata, &enclen, width, height, data, format, step, 0,
221 char encname[128] = { 0 };
222 (void)_snprintf(encname,
sizeof(encname),
"enc-%" PRIu32, bpp);
223#if defined(CREATE_TEST_OUTPUT)
224 test_codec_helper_write_data(
"interleaved", encname, name, encdata, enclen);
226 if (!test_codec_helper_compare(
"interleaved", encname, name, encdata, enclen))
236 bitmap_interleaved_context_free(encoder);
240static bool RunDecoderTest(
const char* name, uint32_t format, uint32_t width, uint32_t height,
241 uint32_t step, uint32_t bpp)
245 void* decdata = NULL;
246 BITMAP_INTERLEAVED_CONTEXT* decoder = bitmap_interleaved_context_new(
false);
250 char encname[128] = { 0 };
251 (void)_snprintf(encname,
sizeof(encname),
"enc-%" PRIu32, bpp);
254 data = test_codec_helper_read_data(
"interleaved", encname, name, &srclen);
258 const size_t declen = 1ULL * step * height;
259 decdata = calloc(step, height);
263 for (
size_t x = 0; x < 42; x++)
265 if (!interleaved_decompress(decoder, data, WINPR_ASSERTING_INT_CAST(uint32_t, srclen),
266 width, height, bpp, decdata, format, step, 0, 0, width, height,
270 char decname[128] = { 0 };
271 (void)_snprintf(decname,
sizeof(decname),
"dec-%s", encname);
272#if defined(CREATE_TEST_OUTPUT)
273 test_codec_helper_write_data(
"interleaved", decname, name, decdata, declen);
275 if (!test_codec_helper_compare(
"interleaved", decname, name, decdata, declen))
285 bitmap_interleaved_context_free(decoder);
304static bool isObjectValid(
const WINPR_JSON* obj)
309 const char* strvalues[] = {
"name",
"format" };
310 for (
size_t x = 0; x < ARRAYSIZE(strvalues); x++)
312 const char* val = strvalues[x];
325 const char* values[] = {
"width",
"height",
"step" };
326 for (
size_t x = 0; x < ARRAYSIZE(values); x++)
328 const char* val = values[x];
342 const char* val =
"bpp";
364static bool TestEncoder(
void)
367 WINPR_JSON* json = NULL;
369 char* path = GetCombinedPath(CMAKE_CURRENT_SOURCE_DIR,
"interleaved");
372 file = GetCombinedPath(path,
"encoder.json");
386 if (!isObjectValid(obj))
390 const uint32_t format = WINPR_ASSERTING_INT_CAST(
391 uint32_t, FreeRDPGetColorFromatFromName(
393 const uint32_t width = WINPR_ASSERTING_INT_CAST(
395 const uint32_t height = WINPR_ASSERTING_INT_CAST(
397 const uint32_t step = WINPR_ASSERTING_INT_CAST(
403 const uint32_t bpp = WINPR_ASSERTING_INT_CAST(
405 if (!RunEncoderTest(name, format, width, height, step, bpp))
407 if (!RunDecoderTest(name, format, width, height, step, bpp))
420int TestFreeRDPCodecInterleaved(
int argc,
char* argv[])
422 BITMAP_INTERLEAVED_CONTEXT* encoder = NULL;
423 BITMAP_INTERLEAVED_CONTEXT* decoder = NULL;
427 encoder = bitmap_interleaved_context_new(
true);
428 decoder = bitmap_interleaved_context_new(
false);
430 if (!encoder || !decoder)
433 if (!run_encode_decode(24, encoder, decoder))
436 if (!run_encode_decode(16, encoder, decoder))
439 if (!run_encode_decode(15, encoder, decoder))
442 if (!TestColorConversion())
450 bitmap_interleaved_context_free(encoder);
451 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_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.