7#include <winpr/sysinfo.h>
9#include <freerdp/freerdp.h>
10#include <freerdp/codec/color.h>
12static const char* print_ns(UINT64 start, UINT64 end,
char* buffer,
size_t len)
14 const UINT64 diff = end - start;
15 const unsigned ns = diff % 1000;
16 const unsigned us = (diff / 1000) % 1000;
17 const unsigned ms = (diff / 1000000) % 1000;
18 const unsigned s = (diff / 1000000000ULL) % 1000;
19 (void)_snprintf(buffer, len,
"%03u %03u %03u %03uns", s, ms, us, ns);
23static BOOL testContextOptions(BOOL compressor, uint32_t width, uint32_t height)
26 const UINT64 start = winpr_GetUnixTimeNS();
27 H264_CONTEXT* h264 = h264_context_new(FALSE);
33 H264_CONTEXT_OPTION opt;
36 const struct optpair_s optpair[] = { { H264_CONTEXT_OPTION_RATECONTROL, H264_RATECONTROL_VBR },
37 { H264_CONTEXT_OPTION_BITRATE, 2323 },
38 { H264_CONTEXT_OPTION_FRAMERATE, 23 },
39 { H264_CONTEXT_OPTION_QP, 21 },
40 { H264_CONTEXT_OPTION_USAGETYPE, 23 } };
41 for (
size_t x = 0; x < ARRAYSIZE(optpair); x++)
43 const struct optpair_s* cur = &optpair[x];
44 if (!h264_context_set_option(h264, cur->opt, cur->val))
47 if (!h264_context_reset(h264, width, height))
52 h264_context_free(h264);
53 const UINT64 end = winpr_GetUnixTimeNS();
55 char buffer[64] = WINPR_C_ARRAY_INIT;
56 printf(
"[%s] %" PRIu32
"x%" PRIu32
" took %s\n", __func__, width, height,
57 print_ns(start, end, buffer,
sizeof(buffer)));
61static void* allocRGB(uint32_t format, uint32_t width, uint32_t height, uint32_t* pstride)
63 const size_t bpp = FreeRDPGetBytesPerPixel(format);
64 const size_t stride = bpp * width + 32;
65 WINPR_ASSERT(pstride);
66 *pstride = WINPR_ASSERTING_INT_CAST(uint32_t, stride);
68 uint8_t* rgb = calloc(stride, height);
72 for (
size_t x = 0; x < height; x++)
74 if (winpr_RAND(&rgb[x * stride], width * bpp) < 0)
83static BOOL compareRGB(
const uint8_t* src,
const uint8_t* dst, uint32_t format,
size_t width,
84 size_t stride,
size_t height)
86 const size_t bpp = FreeRDPGetBytesPerPixel(format);
87 for (
size_t y = 0; y < height; y++)
89 const uint8_t* csrc = &src[y * stride];
90 const uint8_t* cdst = &dst[y * stride];
91 const int rc = memcmp(csrc, cdst, width * bpp);
102static BOOL testEncode(uint32_t format, uint32_t width, uint32_t height)
108 H264_CONTEXT* h264 = h264_context_new(TRUE);
109 H264_CONTEXT* h264dec = h264_context_new(FALSE);
110 if (!h264 || !h264dec)
113 if (!h264_context_reset(h264, width, height))
115 if (!h264_context_reset(h264dec, width, height))
119 uint32_t ostride = 0;
120 src = allocRGB(format, width, height, &stride);
121 out = allocRGB(format, width, height, &ostride);
122 if (!src || !out || (stride < width) || (stride != ostride))
125 const RECTANGLE_16 rect = { .left = 0, .top = 0, .right = width, .bottom = height };
126 uint32_t dstsize = 0;
127 uint8_t* dst =
nullptr;
128 if (avc420_compress(h264, src, format, stride, width, height, &rect, &dst, &dstsize, &meta) < 0)
130 if ((dstsize == 0) || !dst)
133 if (avc420_decompress(h264dec, dst, dstsize, out, format, stride, width, height, &rect, 1) < 0)
136 rc = compareRGB(src, out, format, width, stride, height);
138 h264_context_free(h264);
139 h264_context_free(h264dec);
140 free_h264_metablock(&meta);
146int TestFreeRDPCodecH264(
int argc,
char* argv[])
153 const UINT32 formats[] = {
154 PIXEL_FORMAT_ABGR15, PIXEL_FORMAT_ARGB15, PIXEL_FORMAT_BGR15, PIXEL_FORMAT_BGR16,
155 PIXEL_FORMAT_BGR24, PIXEL_FORMAT_RGB15, PIXEL_FORMAT_RGB16, PIXEL_FORMAT_RGB24,
156 PIXEL_FORMAT_ABGR32, PIXEL_FORMAT_ARGB32, PIXEL_FORMAT_XBGR32, PIXEL_FORMAT_XRGB32,
157 PIXEL_FORMAT_BGRA32, PIXEL_FORMAT_RGBA32, PIXEL_FORMAT_BGRX32, PIXEL_FORMAT_RGBX32,
163 width = strtoul(argv[1],
nullptr, 0);
164 height = strtoul(argv[2],
nullptr, 0);
165 if ((errno != 0) || (width == 0) || (height == 0))
167 char buffer[128] = WINPR_C_ARRAY_INIT;
168 (void)fprintf(stderr,
"%s failed: width=%" PRIu32
", height=%" PRIu32
", errno=%s\n",
169 __func__, width, height, winpr_strerror(errno, buffer,
sizeof(buffer)));
174#if !defined(WITH_MEDIACODEC) && !defined(WITH_MEDIA_FOUNDATION) && !defined(WITH_OPENH264) && \
175 !defined(WITH_VIDEO_FFMPEG)
176 (void)fprintf(stderr,
"[%s] skipping, no H264 encoder/decoder support compiled in\n", __func__);
180 if (!testContextOptions(FALSE, width, height))
182 if (!testContextOptions(TRUE, width, height))
185 for (
size_t x = 0; x < ARRAYSIZE(formats); x++)
187 const UINT32 SrcFormat = formats[x];
188 for (
size_t y = 0; y < ARRAYSIZE(formats); y++)
190 if (!testEncode(SrcFormat, width, height))