20#include <winpr/assert.h>
21#include <freerdp/codec/color.h>
23#include "../../camera.h"
24#include "../../../common/rdpecam-utils.h"
28static BOOL test_h264_encoding(
void)
30 if (!freerdp_video_conversion_supported(FREERDP_VIDEO_FORMAT_NV12, FREERDP_VIDEO_FORMAT_H264))
41 wStream* sample = Stream_New(NULL, 1);
42 H264_CONTEXT* decoder = h264_context_new(FALSE);
43 BYTE raw[width * height * 3 / 2] = { 0 };
44 BYTE rgb[stride * height] = { 0 };
46 stream.formats.inputFormat = CAM_MEDIA_FORMAT_NV12;
47 stream.formats.outputFormat = CAM_MEDIA_FORMAT_H264;
48 stream.currMediaType.Width = width;
49 stream.currMediaType.Height = height;
50 stream.currMediaType.FrameRateNumerator = 30;
51 stream.currMediaType.FrameRateDenominator = 1;
52 if (!sample || !decoder || !ecam_encoder_context_init(&stream) ||
53 !h264_context_reset(decoder, width, height))
56 memset(raw + width * height, 128,
sizeof(raw) - width * height);
57 for (
size_t frame = 0; frame < 3; frame++)
59 memset(raw, (
int)(96 + frame * 16), width * height);
60 memset(rgb, 0xa5,
sizeof(rgb));
61 Stream_ResetPosition(sample);
62 Stream_Write_UINT8(sample, 0x5a);
63 if (!ecam_encoder_compress(&stream, raw,
sizeof(raw), sample) ||
64 (Stream_GetPosition(sample) <= 1) || (Stream_Buffer(sample)[0] != 0x5a))
66 const size_t size = Stream_GetPosition(sample) - 1;
67 if ((size > UINT32_MAX) ||
68 (avc420_decompress(decoder, Stream_Buffer(sample) + 1, (UINT32)size, rgb,
69 PIXEL_FORMAT_BGRA32, stride, width, height, ®ion, 1) < 0))
72 const BYTE* pixel = rgb + (height / 2) * stride + (width / 2) * 4;
73 const int expected = (int)((80 + frame * 16) * 255 / 219);
74 for (
size_t channel = 0; channel < 3; channel++)
76 const int difference = (int)pixel[channel] - expected;
77 if ((difference < -8) || (difference > 8))
83 if (!ecam_encoder_context_free(&stream))
85 h264_context_free(decoder);
86 Stream_Free(sample, TRUE);
88 fprintf(stderr,
"NV12 camera H.264 encoding or decoding failed\n");
93int TestCameraAVFoundationNV12(
int argc,
char* argv[])
98 CVPixelBufferRef image = NULL;
100 wStream* sample = Stream_New(NULL, 1);
102 if (!sample || CVPixelBufferCreate(NULL, 8, 4, kCVPixelFormatType_420YpCbCr8BiPlanarVideoRange,
103 NULL, &image) != kCVReturnSuccess)
105 if (CVPixelBufferLockBaseAddress(image, 0) != kCVReturnSuccess)
107 BYTE expected[48] = { 0 };
109 for (
size_t plane = 0; plane < 2; plane++)
111 BYTE* data = CVPixelBufferGetBaseAddressOfPlane(image, plane);
112 const size_t stride = CVPixelBufferGetBytesPerRowOfPlane(image, plane);
113 for (
size_t row = 0; row < CVPixelBufferGetHeightOfPlane(image, plane); row++)
116 memset(data + row * stride, 0xff, stride);
117 memset(data + row * stride, (
int)(plane * 16 + row), 8);
118 memset(expected + offset, (
int)(plane * 16 + row), 8);
122 CVPixelBufferUnlockBaseAddress(image, 0);
123 if (!cam_avfoundation_pixel_buffer_to_nv12(image, sample) ||
124 (Stream_Length(sample) !=
sizeof(expected)) ||
125 memcmp(Stream_Buffer(sample), expected,
sizeof(expected)) != 0)
129 stream.formats.inputFormat = CAM_MEDIA_FORMAT_NV12;
130 stream.formats.outputFormat = CAM_MEDIA_FORMAT_NV12;
131 stream.currMediaType.Width = 8;
132 stream.currMediaType.Height = 4;
133 stream.currMediaType.FrameRateNumerator = 30;
134 stream.currMediaType.FrameRateDenominator = 1;
135 Stream_ResetPosition(sample);
136 Stream_Write_UINT8(sample, 0x5a);
137 if (!ecam_encoder_context_init(&stream) ||
138 !ecam_encoder_compress(&stream, expected,
sizeof(expected), sample) ||
139 (Stream_GetPosition(sample) !=
sizeof(expected) + 1) ||
140 (Stream_Buffer(sample)[0] != 0x5a) ||
141 memcmp(Stream_Buffer(sample) + 1, expected,
sizeof(expected)) != 0)
144 wLog* flagsLog = WLog_Get(
"camera.test.flags");
145 if (!flagsLog || !WLog_SetLogLevel(flagsLog, WLOG_OFF))
147 for (
unsigned flags = 0; flags <= UINT8_MAX; flags++)
149 const BOOL valid = rdpecam_valid_MediaTypeDescriptionFlags_((UINT8)flags, flagsLog,
150 __FILE__, __func__, __LINE__);
151 if (valid != (flags <= 3))
153 fprintf(stderr,
"Incorrect media type flag validation for 0x%02x\n", flags);
157 CVPixelBufferRef invalid = NULL;
158 if (CVPixelBufferCreate(NULL, 8, 4, kCVPixelFormatType_32ARGB, NULL, &invalid) !=
161 const BOOL accepted = cam_avfoundation_pixel_buffer_to_nv12(invalid, sample);
165 if (!test_h264_encoding())
169 if (!ecam_encoder_context_free(&stream))
173 Stream_Free(sample, TRUE);
175 fprintf(stderr,
"NV12 camera sample packing or flags validation failed\n");