7#include <winpr/sysinfo.h>
9#include <freerdp/freerdp.h>
10#include <freerdp/codec/color.h>
12#if defined(WITH_APPLE_VIDEOTOOLBOX)
13#include <CoreMedia/CoreMedia.h>
14#include <freerdp/codec/video.h>
19static const char* print_ns(UINT64 start, UINT64 end,
char* buffer,
size_t len)
23 const UINT64 diff = end - start;
24 const unsigned ns = diff % 1000;
25 const unsigned us = (diff / 1000) % 1000;
26 const unsigned ms = (diff / 1000000) % 1000;
27 const unsigned s = (diff / 1000000000ULL) % 1000;
28 (void)_snprintf(buffer, len,
"%03u %03u %03u %03uns", s, ms, us, ns);
33static BOOL testContextOptions(BOOL compressor, uint32_t width, uint32_t height)
36 const UINT64 start = winpr_GetUnixTimeNS();
38 H264_CONTEXT* h264 = h264_context_new(compressor);
41 (void)fprintf(stderr,
"[%s] h264_context_new failed\n", __func__);
47 H264_CONTEXT_OPTION opt;
50 const struct optpair_s optpair[] = { { H264_CONTEXT_OPTION_RATECONTROL, H264_RATECONTROL_VBR },
51 { H264_CONTEXT_OPTION_BITRATE, 2323 },
52 { H264_CONTEXT_OPTION_FRAMERATE, 23 },
53 { H264_CONTEXT_OPTION_QP, 21 },
54 { H264_CONTEXT_OPTION_USAGETYPE, 23 } };
55 for (
size_t x = 0; x < ARRAYSIZE(optpair); x++)
57 const struct optpair_s* cur = &optpair[x];
58 if (!h264_context_set_option(h264, cur->opt, cur->val))
61 "[%s] h264_context_set_option %" PRIuz
"{ %d, %" PRIu32
" } failed\n",
62 __func__, x, cur->opt, cur->val);
66 if (!h264_context_reset(h264, width, height))
68 (void)fprintf(stderr,
"[%s] h264_context_reset\n", __func__);
74 h264_context_free(h264);
75 const UINT64 end = winpr_GetUnixTimeNS();
77 char buffer[64] = WINPR_C_ARRAY_INIT;
78 printf(
"[%s] %" PRIu32
"x%" PRIu32
" took %s\n", __func__, width, height,
79 print_ns(start, end, buffer,
sizeof(buffer)));
83WINPR_ATTR_MALLOC(free, 1)
84static
void* allocRGB(uint32_t format, uint32_t width, uint32_t height, uint32_t* pstride)
86 const size_t bpp = FreeRDPGetBytesPerPixel(format);
87 const size_t stride = bpp * width + 32;
88 WINPR_ASSERT(pstride);
89 *pstride = WINPR_ASSERTING_INT_CAST(uint32_t, stride);
91 uint8_t* rgb = calloc(stride, height);
95 const UINT32 color = FreeRDPGetColor(format, 0x12, 0xaa, 0x63, 0x80);
96 for (
size_t y = 0; y < height; y++)
98 uint8_t* line = &rgb[y * stride];
99 for (
size_t x = 0; x < width; x++)
101 FreeRDPWriteColor(&line[bpp * x], format, color);
108#define printIfFail(line, offset, what, a, b) \
109 printIfFail_(__func__, __LINE__, (line), (offset), (what), (a), (b))
110static BOOL printIfFail_(
const char* fkt,
size_t fline,
size_t line,
size_t offset,
111 const char* what, BYTE a, BYTE b)
113 const double maxDiff = 8.0;
114 const double diffR = fabs(1.0 * a - b);
117 (void)fprintf(stderr,
118 "[%s:%" PRIuz
"]{%" PRIuz
"x%" PRIuz
"} %s diff %lf [0x%02" PRIx8
119 " - 0x%02" PRIx8
"]\n",
120 fkt, fline, offset, line, what, diffR, a, b);
127static BOOL compareRGBColors(
size_t line,
size_t offset, uint32_t colora, uint32_t colorb,
139 FreeRDPSplitColor(colora, format, &cR, &cG, &cB, &cA,
nullptr);
140 FreeRDPSplitColor(colorb, format, &dR, &dG, &dB, &dA,
nullptr);
142 if (!printIfFail(line, offset,
"red", cR, dR))
144 if (!printIfFail(line, offset,
"green", cG, dG))
146 if (!printIfFail(line, offset,
"blue", cB, dB))
148 if (FreeRDPColorHasAlpha(format))
150 if (!printIfFail(line, offset,
"alpha", cA, dA))
157static BOOL compareRGBLine(
size_t line,
const uint8_t* src,
const uint8_t* dst, uint32_t format,
160 const size_t bpp = FreeRDPGetBytesPerPixel(format);
161 for (
size_t x = 0; x < width; x++)
163 const UINT32 srccolor = FreeRDPReadColor(&src[x * bpp], format);
164 const UINT32 dstcolor = FreeRDPReadColor(&dst[x * bpp], format);
165 if (!compareRGBColors(line, x, srccolor, dstcolor, format))
172static BOOL compareRGB(
const uint8_t* src,
const uint8_t* dst, uint32_t format,
size_t width,
173 size_t stride,
size_t height)
178 const size_t bits = FreeRDPGetBitsPerPixel(format);
181 printf(
"skipping color compare for format %s, only 32bpp colors are checked\n",
182 FreeRDPGetColorFormatName(format));
186 for (
size_t y = 0; y < height; y++)
188 const uint8_t* csrc = &src[y * stride];
189 const uint8_t* cdst = &dst[y * stride];
190 if (!compareRGBLine(y, csrc, cdst, format, width))
197static BOOL testEncode(uint32_t format, uint32_t width, uint32_t height)
202 void* copy =
nullptr;
204 H264_CONTEXT* h264 = h264_context_new(TRUE);
205 H264_CONTEXT* h264dec = h264_context_new(FALSE);
206 if (!h264 || !h264dec)
208 (void)fprintf(stderr,
"[%s] encoder=%p, decoder=%p\n", __func__, (
void*)h264,
213 if (!h264_context_reset(h264, width, height))
215 (void)fprintf(stderr,
"[%s] h264_context_reset(encoder) failed\n", __func__);
218 if (!h264_context_reset(h264dec, width, height))
220 (void)fprintf(stderr,
"[%s] h264_context_reset(decoder) failed\n", __func__);
225 uint32_t ostride = 0;
226 src = allocRGB(format, width, height, &stride);
227 out = allocRGB(format, width, height, &ostride);
228 if (!src || !out || (stride < width) || (stride != ostride))
230 (void)fprintf(stderr,
231 "[%s] src=%p, out=%p, stride(%" PRIu32
") < width(%" PRIu32
232 "), stride != ostride(%" PRIu32
")\n",
233 __func__, src, out, stride, width, ostride);
237 copy = calloc(height, stride);
240 memcpy(copy, src, 1ull * height * stride);
242 const RECTANGLE_16 rect = { .left = 0, .top = 0, .right = width, .bottom = height };
243 uint32_t dstsize = 0;
244 uint8_t* dst =
nullptr;
246 avc420_compress(h264, src, format, stride, width, height, &rect, &dst, &dstsize, &meta);
249 (void)fprintf(stderr,
"[%s] avc420_compress failed: %d\n", __func__, res1);
252 if ((dstsize == 0) || !dst)
254 (void)fprintf(stderr,
"[%s] dstsize=%" PRIu32
", dst=%p\n", __func__, dstsize, (
void*)dst);
257 if (memcmp(copy, src, 1ull * height * stride) != 0)
259 (void)fprintf(stderr,
"[%s] avc420_compress modified source data!\n", __func__);
264 avc420_decompress(h264dec, dst, dstsize, out, format, stride, width, height, &rect, 1);
267 (void)fprintf(stderr,
"[%s] avc420_decompress failed: %d\n", __func__, res2);
271 rc = compareRGB(src, out, format, width, stride, height);
274 (void)fprintf(stderr,
"[%s] run failed\n", __func__);
275 h264_context_free(h264);
276 h264_context_free(h264dec);
277 free_h264_metablock(&meta);
285static BOOL testEncodeOffsetRegion(
void)
288 const UINT32 width = 192;
289 const UINT32 height = 128;
290 const UINT32 format = PIXEL_FORMAT_BGRA32;
291 const RECTANGLE_16 full = { .left = 0, .top = 0, .right = width, .bottom = height };
292 const RECTANGLE_16 region = { .left = 32, .top = 16, .right = 160, .bottom = 112 };
294 H264_CONTEXT* h264 = h264_context_new(TRUE);
296 BYTE* src = allocRGB(format, width, height, &stride);
300 if (!h264 || !src || !h264_context_reset(h264, width, height))
303 memset(src, 0, (
size_t)stride * height);
305 avc420_compress(h264, src, format, stride, width, height, &full, &dst, &dstSize, &meta);
309 (void)fprintf(stderr,
"[%s] first avc420_compress failed: %d\n", __func__, res);
312 free_h264_metablock(&meta);
314 for (UINT32 y = region.top; y < region.bottom; y++)
316 BYTE* row = &src[(size_t)y * stride + (
size_t)region.left * 4];
317 memset(row, 0xFF, (
size_t)(region.right - region.left) * 4);
323 avc420_compress(h264, src, format, stride, width, height, ®ion, &dst, &dstSize, &meta);
326 (void)fprintf(stderr,
"[%s] second avc420_compress failed: %d\n", __func__, res2);
329 if ((meta.numRegionRects == 0) || (meta.regionRects[0].left != region.left) ||
330 (meta.regionRects[0].top != region.top))
333 stderr,
"%s failed: first changed tile does not start at (%" PRIu16
", %" PRIu16
")\n",
334 __func__, region.left, region.top);
341 (void)fprintf(stderr,
"[%s] run failed\n", __func__);
342 h264_context_free(h264);
343 free_h264_metablock(&meta);
351static const BYTE solid_idr_64x64[] = {
352 0x00, 0x00, 0x00, 0x01, 0x67, 0x42, 0xc0, 0x0a, 0xd9, 0x04, 0x26, 0xc0, 0x44, 0x00,
353 0x00, 0x03, 0x00, 0x04, 0x00, 0x00, 0x03, 0x00, 0xc8, 0x3c, 0x48, 0x99, 0x20, 0x00,
354 0x00, 0x00, 0x01, 0x68, 0xcb, 0x83, 0xcb, 0x20, 0x00, 0x00, 0x01, 0x65, 0x88, 0x84,
355 0x0a, 0xf1, 0x18, 0xa0, 0x00, 0x22, 0x4b, 0x1c, 0x00, 0x04, 0x53, 0xa3, 0x80, 0x00,
356 0x85, 0x8c, 0x9c, 0x9c, 0x9d, 0x75, 0xd7, 0x5d, 0x75, 0xd7, 0x5d, 0x75, 0xd7, 0x5e
360static BOOL testDecode(BOOL separateParameters)
363 const UINT32 width = 64;
364 const UINT32 height = 64;
365 const UINT32 format = PIXEL_FORMAT_BGRX32;
366 const UINT32 stride = width * 4;
367 const RECTANGLE_16 rect = { .left = 0, .top = 0, .right = width, .bottom = height };
368 H264_CONTEXT* h264 = h264_context_new(FALSE);
369 BYTE* dst = calloc(stride, height);
371 if (!h264 || !dst || !h264_context_reset(h264, width, height))
375 const UINT32 offset = separateParameters ? 36 : 0;
376 if (separateParameters && (avc420_decompress(h264, solid_idr_64x64, offset, dst, format, stride,
377 width, height, &rect, 1) < 0))
382 avc420_decompress(h264, solid_idr_64x64 + offset,
sizeof(solid_idr_64x64) - offset, dst,
383 format, stride, width, height, &rect, 1);
386 (void)fprintf(stderr,
"[%s] avc420_decompress failed: %" PRId32
"\n", __func__, res);
390 for (UINT32 y = 0; y < height; y++)
392 for (UINT32 x = 0; x < width; x++)
397 const UINT32 color = FreeRDPReadColor(&dst[y * stride + x * 4], format);
398 FreeRDPSplitColor(color, format, &r, &g, &b,
nullptr,
nullptr);
399 if ((abs(r - 0x33) > 16) || (abs(g - 0x66) > 16) || (abs(b - 0xCC) > 16))
402 stderr,
"[%s] pixel %" PRIu32
",%" PRIu32
" is %02X%02X%02X, expected 3366CC\n",
403 __func__, x, y, r, g, b);
411 h264_context_free(h264);
419static const BYTE avc444_idr[] = {
420 0x00, 0x00, 0x00, 0x01, 0x67, 0x64, 0x00, 0x0A, 0xAC, 0xB2, 0x08, 0x4D, 0x08, 0x00, 0x00, 0x03,
421 0x00, 0x08, 0x00, 0x00, 0x03, 0x01, 0xE0, 0x78, 0x91, 0x32, 0x40, 0x00, 0x00, 0x00, 0x01, 0x68,
422 0xEB, 0xC0, 0x8C, 0xB2, 0x2C, 0x00, 0x00, 0x00, 0x01, 0x09, 0x10, 0x00, 0x00, 0x01, 0x65, 0x88,
423 0x84, 0x3A, 0xFE, 0xC7, 0x6F, 0xE6, 0x59, 0x2A, 0x80, 0xC4, 0x0B, 0xD4, 0xF7, 0xD5, 0xB5, 0x93,
424 0x2C, 0x2D, 0x6E, 0xCB, 0x72, 0xFB, 0xC9, 0x1D, 0x47, 0x81, 0x00, 0x00, 0x01, 0x65, 0x12, 0x22,
425 0x10, 0xEB, 0xFE, 0xC7, 0x6F, 0xE6, 0x59, 0x2A, 0x80, 0xC4, 0x0B, 0xD4, 0xF7, 0xD5, 0xB5, 0x93,
426 0x2C, 0x2D, 0x6E, 0xCB, 0x72, 0xFB, 0xC9, 0x1D, 0x47, 0x81,
429static const BYTE avc444_p[] = {
430 0x00, 0x00, 0x00, 0x01, 0x09, 0x30, 0x00, 0x00, 0x01, 0x41, 0x9A, 0x3B, 0x1F, 0xF9,
431 0x59, 0xCD, 0xEF, 0xFF, 0xFC, 0xF8, 0xAA, 0xD6, 0x9F, 0x73, 0x05, 0x6A, 0x32, 0x45,
432 0xA5, 0x7B, 0x00, 0x00, 0x01, 0x41, 0x12, 0x68, 0xEC, 0x7F, 0xFA, 0xE1, 0x80,
436static BOOL testDecodeAvc444(UINT32 codec)
441 const UINT32 stride = 64 * 4;
442 const UINT32 format = PIXEL_FORMAT_BGRX32;
443 const BYTE untouched[4] = { 0xA5, 0xA5, 0xA5, 0xA5 };
444 const size_t sampleOffset = partial.top * stride + partial.left * 4;
445 BYTE luma[4] = WINPR_C_ARRAY_INIT;
446 BYTE combined[64 * 64 * 4] = WINPR_C_ARRAY_INIT;
447 BYTE separate[64 * 64 * 4] = WINPR_C_ARRAY_INIT;
448 H264_CONTEXT* combinedContext = h264_context_new(FALSE);
449 H264_CONTEXT* separateContext = h264_context_new(FALSE);
451 if (!combinedContext || !separateContext || !h264_context_reset(combinedContext, 64, 64) ||
452 !h264_context_reset(separateContext, 64, 64))
454 memset(separate, 0xA5,
sizeof(separate));
457 if (avc444_decompress(combinedContext, 0, &full, 1, avc444_idr,
sizeof(avc444_idr), &full, 1,
458 avc444_p,
sizeof(avc444_p), combined, format, stride, 64, 64, codec) != 0)
462 if (avc444_decompress(separateContext, 1, &partial, 1, avc444_idr,
sizeof(avc444_idr),
nullptr,
463 0,
nullptr, 0, separate, format, stride, 64, 64, codec) != 0)
465 memcpy(luma, &separate[sampleOffset],
sizeof(luma));
466 if (avc444_decompress(separateContext, 2, &partial, 1, avc444_p,
sizeof(avc444_p),
nullptr, 0,
467 nullptr, 0, separate, format, stride, 64, 64, codec) != 0)
471 if ((memcmp(luma, untouched,
sizeof(luma)) == 0) ||
472 (memcmp(luma, &separate[sampleOffset],
sizeof(luma)) == 0))
474 (void)fprintf(stderr,
"[%s] missing main or auxiliary output\n", __func__);
479 for (UINT32 y = 0; y < 64; y++)
481 for (UINT32 x = 0; x < 64; x++)
483 const size_t offset = y * stride + x * 4;
484 const BOOL inside = (x >= partial.left) && (x < partial.right) && (y >= partial.top) &&
485 (y < partial.bottom);
486 const BYTE* expected = inside ? &combined[offset] : untouched;
487 if (memcmp(&separate[offset], expected, inside ? 3 : 4) != 0)
489 (void)fprintf(stderr,
"[%s] pixel %" PRIu32
",%" PRIu32
" differs\n", __func__, x,
499 (void)fprintf(stderr,
"[%s] codec 0x%04" PRIX32
" failed\n", __func__, codec);
500 h264_context_free(combinedContext);
501 h264_context_free(separateContext);
505#if defined(WITH_APPLE_VIDEOTOOLBOX)
508static BOOL testH264Range(
const BYTE* data,
size_t size, BOOL fullRange)
511 const BYTE startCode[] = { 0, 0, 0, 1 };
512 const BYTE* parameters[2] = WINPR_C_ARRAY_INIT;
513 size_t lengths[2] = WINPR_C_ARRAY_INIT;
515 for (
size_t i = 0; i < ARRAYSIZE(parameters); i++)
517 if ((size - offset < 5) || (memcmp(data + offset, startCode,
sizeof(startCode)) != 0) ||
518 ((data[offset + 4] & 0x1F) != 7 + i))
520 offset +=
sizeof(startCode);
521 parameters[i] = data + offset;
522 const size_t start = offset;
523 while ((size - offset >=
sizeof(startCode)) &&
524 (memcmp(data + offset, startCode,
sizeof(startCode)) != 0))
526 if (size - offset <
sizeof(startCode))
528 lengths[i] = offset - start;
530 CMVideoFormatDescriptionRef format =
nullptr;
531 if (CMVideoFormatDescriptionCreateFromH264ParameterSets(
532 kCFAllocatorDefault, ARRAYSIZE(parameters), parameters, lengths, 4, &format) != noErr)
534 const BOOL actual = CMFormatDescriptionGetExtension(
535 format, kCMFormatDescriptionExtension_FullRangeVideo) == kCFBooleanTrue
539 if (actual != fullRange)
540 (void)fprintf(stderr,
"[%s] full range %d, expected %d\n", __func__, actual, fullRange);
541 return actual == fullRange ? TRUE : FALSE;
545static BOOL testCameraEncode(UINT32 width, UINT32 height)
548 const BYTE samples[][3] = { { 16, 128, 128 }, { 235, 128, 128 }, { 96, 64, 192 } };
549 const size_t pixels = (size_t)width * height;
550 BYTE* nv12 = calloc(pixels * 3 / 2, 1);
551 wStream* output = Stream_New(
nullptr, 1);
552 FREERDP_VIDEO_CONTEXT* video = freerdp_video_context_new(width, height);
553 H264_CONTEXT* decoder = h264_context_new(FALSE);
554 if (!nv12 || !output || !video || !decoder || !h264_context_reset(decoder, width, height) ||
555 !freerdp_video_conversion_supported(FREERDP_VIDEO_FORMAT_NV12, FREERDP_VIDEO_FORMAT_H264))
558 for (
size_t frame = 0; frame < ARRAYSIZE(samples); frame++)
561 if (!freerdp_video_context_reconfigure(video, width, height, 30, 0,
562 H264_CAMERA_VIDEO_REAL_TIME))
564 memset(nv12, samples[frame][0], pixels);
565 for (
size_t i = 0; i < pixels / 2; i += 2)
567 nv12[pixels + i] = samples[frame][1];
568 nv12[pixels + i + 1] = samples[frame][2];
570 Stream_ResetPosition(output);
571 Stream_Write_UINT8(output, 0x5a);
572 if (!freerdp_video_sample_convert(video, FREERDP_VIDEO_FORMAT_NV12, nv12, pixels * 3 / 2,
573 FREERDP_VIDEO_FORMAT_H264, output) ||
574 (Stream_GetPosition(output) <= 1) || (Stream_Buffer(output)[0] != 0x5a))
576 const BYTE* encoded = Stream_Buffer(output) + 1;
577 const size_t size = Stream_GetPosition(output) - 1;
578 if ((size > UINT32_MAX) || ((frame == 0) && !testH264Range(encoded, size, FALSE)) ||
579 (decoder->subsystem->Decompress(decoder, encoded, (UINT32)size) <= 0))
582 for (
size_t plane = 0; plane < 3; plane++)
584 const UINT32 divisor = plane == 0 ? 1 : 2;
585 const size_t center =
586 (size_t)(height / (2 * divisor)) * decoder->iStride[plane] + width / (2 * divisor);
587 if (!decoder->pYUVData[plane] ||
588 (abs(decoder->pYUVData[plane][center] - samples[frame][plane]) > 4))
595 (void)fprintf(stderr,
"[%s] NV12 camera encoding failed at %" PRIu32
"x%" PRIu32
"\n",
596 __func__, width, height);
597 h264_context_free(decoder);
598 freerdp_video_context_free(video);
599 Stream_Free(output, TRUE);
605static BOOL testEncodeRange(
void)
608 H264_CONTEXT* encoder = h264_context_new(TRUE);
609 if (!encoder || !h264_context_reset(encoder, 64, 48))
611 BYTE* planes[3] = WINPR_C_ARRAY_INIT;
612 UINT32 strides[3] = WINPR_C_ARRAY_INIT;
613 if (h264_get_yuv_buffer(encoder, 64, 64, 48, planes, strides) < 0)
615 for (
size_t plane = 0; plane < 3; plane++)
616 memset(planes[plane], 128, (
size_t)strides[plane] * (plane == 0 ? 48 : 24));
617 const H264_USAGETYPE usage[] = { H264_SCREEN_CONTENT_REAL_TIME, H264_CAMERA_VIDEO_REAL_TIME,
618 H264_SCREEN_CONTENT_NON_REAL_TIME,
619 H264_CAMERA_VIDEO_NON_REAL_TIME,
620 H264_SCREEN_CONTENT_REAL_TIME };
621 for (
size_t i = 0; i < ARRAYSIZE(usage); i++)
623 BYTE* encoded =
nullptr;
625 const BOOL fullRange = i % 2 == 0 ? TRUE : FALSE;
626 if (!h264_context_set_option(encoder, H264_CONTEXT_OPTION_USAGETYPE, usage[i]) ||
627 (h264_context_get_option(encoder, H264_CONTEXT_OPTION_USAGETYPE) != usage[i]) ||
628 (h264_compress(encoder, &encoded, &size) < 0) || !encoded ||
629 !testH264Range(encoded, size, fullRange))
635 (void)fprintf(stderr,
"[%s] encoder range change failed\n", __func__);
636 h264_context_free(encoder);
642int TestFreeRDPCodecH264(
int argc,
char* argv[])
651 const UINT32 formats[] = {
652 PIXEL_FORMAT_ABGR15, PIXEL_FORMAT_ARGB15, PIXEL_FORMAT_BGR15, PIXEL_FORMAT_BGR16,
653 PIXEL_FORMAT_BGR24, PIXEL_FORMAT_RGB15, PIXEL_FORMAT_RGB16, PIXEL_FORMAT_RGB24,
654 PIXEL_FORMAT_ABGR32, PIXEL_FORMAT_ARGB32, PIXEL_FORMAT_XBGR32, PIXEL_FORMAT_XRGB32,
655 PIXEL_FORMAT_BGRA32, PIXEL_FORMAT_RGBA32, PIXEL_FORMAT_BGRX32, PIXEL_FORMAT_RGBX32,
661 width = strtoul(argv[1],
nullptr, 0);
662 height = strtoul(argv[2],
nullptr, 0);
663 if ((errno != 0) || (width == 0) || (height == 0))
665 char buffer[128] = WINPR_C_ARRAY_INIT;
666 (void)fprintf(stderr,
"%s failed: width=%" PRIu32
", height=%" PRIu32
", errno=%s\n",
667 __func__, width, height, winpr_strerror(errno, buffer,
sizeof(buffer)));
673#if !defined(WITH_GFX_H264)
674 (void)fprintf(stderr,
"[%s] skipping, no H264 encoder/decoder support compiled in\n", __func__);
678#if defined(WITH_H264_WEBCODECS)
680 H264_CONTEXT* probe = h264_context_new(FALSE);
683 (void)fprintf(stderr,
"[%s] skipping, the runtime cannot decode H.264 with WebCodecs\n",
687 h264_context_free(probe);
691 if (!testContextOptions(FALSE, width, height))
693 if (!testDecode(FALSE))
695#if defined(WITH_APPLE_VIDEOTOOLBOX) || defined(WITH_H264_WEBCODECS)
696 if (!testDecode(TRUE))
700 if (!testDecodeAvc444(RDPGFX_CODECID_AVC444) || !testDecodeAvc444(RDPGFX_CODECID_AVC444v2))
703#if defined(WITH_MEDIA_FOUNDATION) || defined(WITH_OPENH264) || defined(WITH_VIDEO_FFMPEG) || \
704 defined(WITH_MEDIACODEC) || defined(WITH_APPLE_VIDEOTOOLBOX)
705#if defined(WITH_MEDIA_FOUNDATION)
708 H264_CONTEXT* encoder = h264_context_new(TRUE);
711 (void)fprintf(stderr,
"[%s] H.264 compression tests skipped: no encoder on this system\n",
715 h264_context_free(encoder);
719 if (!testContextOptions(TRUE, width, height))
721 if (!testEncodeOffsetRegion())
724#if defined(WITH_APPLE_VIDEOTOOLBOX)
725 H264_CONTEXT* vtEncoder = h264_context_new(TRUE);
726 const BOOL useVideoToolbox =
727 vtEncoder && (strcmp(vtEncoder->subsystem->name,
"VideoToolbox") == 0) ? TRUE : FALSE;
728 h264_context_free(vtEncoder);
731 if (!testCameraEncode(64, 48) || !testCameraEncode(128, 96) || !testEncodeRange())
736 for (
size_t x = 0; x < ARRAYSIZE(formats); x++)
738 const UINT32 SrcFormat = formats[x];
739 for (
size_t y = 0; y < ARRAYSIZE(formats); y++)
741 if (!testEncode(SrcFormat, width, height))
746 (void)fprintf(stderr,
"H.264 compression tests skipped: no encoder configured\n");