24using namespace std::string_literals;
30using std::default_random_engine;
31using std::uniform_int_distribution;
38constexpr int MIN_12B = 16;
39constexpr int MAX_12B = 4079;
42 int ff_codec_conversions_test_yuv444pXXle_from_to_r10k();
43 int ff_codec_conversions_test_yuv444pXXle_from_to_r12l();
44 int ff_codec_conversions_test_yuv444p16le_from_to_rg48();
45 int ff_codec_conversions_test_yuv444p16le_from_to_rg48_out_of_range();
46 int ff_codec_conversions_test_pX10_from_to_v210();
49#define CHECK(res) if ((res) != 0) { return res; }
51#define TIMER(t) struct timeval t{}; gettimeofday(&(t), nullptr)
52int ff_codec_conversions_test_yuv444pXXle_from_to_r10k()
54 using namespace std::string_literals;
56 constexpr int width = 320;
57 constexpr int height = 240;
58 vector <unsigned char> rgba_buf(width * height * 4);
61 auto test_pattern = [&](AVPixelFormat avfmt) {
62 vector <unsigned char> r10k_buf(width * height * 4);
69 assert(to_conv !=
nullptr && from_conv !=
nullptr);
79 if (getenv(
"PERF") !=
nullptr) {
80 cout <<
"test_yuv444p16le_from_to_r10k: duration - enc " <<
tv_diff(t1, t0) <<
", dec " <<
tv_diff(t2, t1) <<
"\n";
83 vector <unsigned char> rgba_buf_res(width * height * 4);
88 for (
size_t i = 0; i < width * height; ++i) {
89 for (
int j = 0; j < 3; ++j) {
90 max_diff =
max<int>(max_diff,
abs(rgba_buf[4 * i + j] - rgba_buf_res[4 * i + j]));
96 if (getenv(
"DEBUG_DUMP") !=
nullptr) {
97 FILE *out = fopen(
"out.rgba",
"w");
98 fwrite(rgba_buf_res.data(), width * height * 4, 1, out);
102 ASSERT_MESSAGE(
"Maximal allowed difference 1, found "s + to_string(max_diff), max_diff <= 1);
106 for (
auto f : { AV_PIX_FMT_YUV444P10LE, AV_PIX_FMT_YUV444P12LE, AV_PIX_FMT_YUV444P16LE }) {
108 for_each(rgba_buf.begin(), rgba_buf.end(), [&](
unsigned char & c) { c = (i++ / 4) % 0x100; });
109 CHECK(test_pattern(f));
111 array<unsigned char, 4>
pattern{ 0xFFU, 0, 0, 0xFFU };
112 for_each(rgba_buf.begin(), rgba_buf.end(), [&](
unsigned char & c) { c = pattern[i++ % 4]; });
113 CHECK(test_pattern(f));
115 default_random_engine rand_gen;
116 for_each(rgba_buf.begin(), rgba_buf.end(), [&](
unsigned char & c) { c = rand_gen() % 0x100; });
117 CHECK(test_pattern(f));
122int ff_codec_conversions_test_yuv444pXXle_from_to_r12l()
124 using namespace std::string_literals;
126 constexpr int width = 320;
127 constexpr int height = 240;
128 vector <unsigned char> rgb_buf(width * height * 3);
130 auto test_pattern = [&](AVPixelFormat avfmt) {
133 rgb_to_r12l(r12l_buf.data(), rgb_buf.data(),
vc_get_datalen(width, height,
R12L), 0, 8, 16);
137 assert(to_conv !=
nullptr && from_conv !=
nullptr);
140 struct AVFrame *converted =
to_lavc_vid_conv(from_conv, (
char *) r12l_buf.data());
147 if (getenv(
"PERF") !=
nullptr) {
148 cout <<
"test_yuv444p16le_from_to_r12l: duration - enc " <<
tv_diff(t1, t0) <<
", dec " <<
tv_diff(t2, t1) <<
"\n";
152 vector <unsigned char> rgb_buf_res(width * height * 3);
154 r12l_to_rgb(rgb_buf_res.data(), r12l_buf.data(),
vc_get_datalen(width, height,
RGB), 0, 8, 16);
157 for (
size_t i = 0; i < width * height; ++i) {
158 for (
int j = 0; j < 3; ++j) {
159 max_diff =
max<int>(max_diff,
abs(rgb_buf[3 * i + j] - rgb_buf_res[3 * i + j]));
163 if (getenv(
"DEBUG_DUMP") !=
nullptr) {
164 FILE *out = fopen(
"out.rgb",
"w");
165 fwrite(rgb_buf_res.data(), width * height * 3, 1, out);
169 ASSERT_MESSAGE(
"Maximal allowed difference 1, found "s + to_string(max_diff), max_diff <= 1);
173 for (
auto f : { AV_PIX_FMT_YUV444P10LE, AV_PIX_FMT_YUV444P12LE, AV_PIX_FMT_YUV444P16LE }) {
175 array<unsigned char, 3>
pattern{ 0xFFU, 0, 0 };
176 for_each(rgb_buf.begin(), rgb_buf.end(), [&](
unsigned char & c) { c = pattern[i++ % 3]; });
177 CHECK(test_pattern(f));
179 for_each(rgb_buf.begin(), rgb_buf.end(), [&](
unsigned char & c) { c = (i++ / 3) % 0x100; });
180 CHECK(test_pattern(f));
182 default_random_engine rand_gen;
183 for_each(rgb_buf.begin(), rgb_buf.end(), [&](
unsigned char & c) { c = rand_gen() % 0x100; });
184 CHECK(test_pattern(f));
189static void yuv444p16le_rg48_encode_decode(
int width,
int height,
char *in,
char *out) {
190 AVPixelFormat avfmt = AV_PIX_FMT_YUV444P16LE;
194 assert(to_conv && from_conv !=
nullptr);
204 if (getenv(
"PERF") !=
nullptr) {
205 cout <<
"test_yuv444p16le_from_to_rg48: duration - enc " <<
tv_diff(t1, t0) <<
", dec " <<
tv_diff(t2, t1) <<
"\n";
214int ff_codec_conversions_test_yuv444p16le_from_to_rg48_out_of_range()
216 using namespace std::string_literals;
218 constexpr int MAX_DIFF = 16;
220 constexpr int width = 4096;
221 constexpr int height = 5;
222 vector <uint16_t> rg48_buf(width * height * 3);
223 vector <uint16_t> rg48_buf_res(width * height * 3);
225 for (
int i = 0; i < 4096; i += 1) {
227 rg48_buf[3 * i + 1] =
228 rg48_buf[3 * i + 2] = 65535 * i / 4095;
230 for (
int line = 0; line < 3; ++line) {
231 for (
int i = 0; i < 4096; i += 1) {
232 rg48_buf[(line + 1) * (width * 3) + 3 * i + line] = 65535 * i / 4095;
235 for (
int i = 0; i < 4096; i += 1) {
236 rg48_buf[4 * (width * 3) + 3 * i] = 65535;
237 rg48_buf[4 * (width * 3) + 3 * i + 1] = 65535;
238 rg48_buf[4 * (width * 3) + 3 * i + 2] = 0;
241 yuv444p16le_rg48_encode_decode(width, height,
reinterpret_cast<char *
>(rg48_buf.data()),
242 reinterpret_cast<char *
>(rg48_buf_res.data()));
245 for (
size_t i = 0; i < width * height; ++i) {
246 for (
int j = 0; j < 3; ++j) {
247 int in = rg48_buf[3 * i + j];
248 in =
min(
max(MIN_12B << 4U, in), MAX_12B << 4U);
249 int out = rg48_buf_res[3 * i + j];
251 if (
abs(diff) >= MAX_DIFF && getenv(
"DEBUG") !=
nullptr) {
252 cout <<
"different value at pos: " << i <<
"," << j <<
" diff: " << diff <<
"\n";
256 ASSERT_MESSAGE(
"Value "s + to_string(out) +
" out of range "s + to_string(MIN_12B) +
"-"s + to_string(MAX_12B), out >= MIN_12B && out <= MAX_12B);
260 if (getenv(
"DEBUG_DUMP") !=
nullptr) {
261 std::ofstream in(
"in.rg48", std::ifstream::out | std::ifstream::binary);
262 in.write(
reinterpret_cast<char *
>(rg48_buf.data()), rg48_buf.size() *
sizeof(
decltype(rg48_buf)::value_type));
263 std::ofstream out(
"out.rg48", std::ifstream::out | std::ifstream::binary);
264 out.write(
reinterpret_cast<char *
>(rg48_buf_res.data()), rg48_buf_res.size() *
sizeof(
decltype(rg48_buf_res)::value_type));
267 ASSERT_MESSAGE(
"Maximal allowed difference "s + to_string (MAX_DIFF) +
"/65535, found "s + to_string(max_diff), max_diff <= MAX_DIFF);
275int ff_codec_conversions_test_yuv444p16le_from_to_rg48()
277 constexpr int MAX_DIFF = 16;
281 vector <uint16_t> rg48_buf(width * height * 3, MIN_12B << 4);
282 vector <uint16_t> rg48_buf_res(width * height * 3);
284 for (
int i = 16; i < 2040; i += 1) {
286 rg48_buf[3 * i + 1] =
287 rg48_buf[3 * i + 2] = (i * 2) << 4;
289 for (
int i = 2040; i < 2048; i += 1) {
291 rg48_buf[3 * i + 1] =
292 rg48_buf[3 * i + 2] = MAX_12B << 4;
295 if (getenv(
"UG_TEST_RG48_INPUT") !=
nullptr) {
296 char *cpy = strdup(getenv(
"UG_TEST_RG48_INPUT"));
297 char *filename = strtok(cpy,
":");
298 width = atoi(strtok(
nullptr,
":"));
299 height = atoi(strtok(
nullptr,
":"));
300 rg48_buf.resize(width * height * 3);
301 rg48_buf_res.resize(width * height * 3);
302 ifstream in(filename, std::ifstream::in | std::ifstream::binary);
303 in.read(
reinterpret_cast<char *
>(rg48_buf.data()), rg48_buf.size() *
sizeof(
decltype(rg48_buf)::value_type));
306 yuv444p16le_rg48_encode_decode(width, height,
reinterpret_cast<char *
>(rg48_buf.data()),
307 reinterpret_cast<char *
>(rg48_buf_res.data()));
310 for (
int i = 0; i < width * height; ++i) {
311 for (
int j = 0; j < 3; ++j) {
312 int in = rg48_buf[3 * i + j];
313 int out = rg48_buf_res[3 * i + j];
315 if (
abs(diff) >= MAX_DIFF && getenv(
"DEBUG") !=
nullptr) {
316 cout <<
"different value at pos: " << i <<
"," << j <<
" diff: " << diff <<
" in: " << in <<
" out: " << out <<
"\n";
320 ASSERT_MESSAGE(
"Value "s + to_string(out) +
" out of range "s + to_string(MIN_12B) +
"-"s + to_string(MAX_12B), out >= MIN_12B && out <= MAX_12B);
324 if (getenv(
"DEBUG_DUMP") !=
nullptr) {
325 std::ofstream in(
"in.rg48", std::ifstream::out | std::ifstream::binary);
326 in.write(
reinterpret_cast<char *
>(rg48_buf.data()), rg48_buf.size() *
sizeof(
decltype(rg48_buf)::value_type));
327 std::ofstream out(
"out.rg48", std::ifstream::out | std::ifstream::binary);
328 out.write(
reinterpret_cast<char *
>(rg48_buf_res.data()), rg48_buf_res.size() *
sizeof(
decltype(rg48_buf_res)::value_type));
331 ASSERT_MESSAGE(
"Maximal allowed difference "s + to_string (MAX_DIFF) +
"/65535, found "s + to_string(max_diff), max_diff <= MAX_DIFF);
340int ff_codec_conversions_test_pX10_from_to_v210()
343 constexpr long width = 1920;
344 constexpr long height = 4;
346 vector <uint32_t> in(height * linesize /
sizeof(uint32_t));
347 vector <uint32_t> out(height * linesize /
sizeof(uint32_t));
348 default_random_engine rand_gen;
349 uniform_int_distribution<uint32_t> dist(0, 0x3fffffffLU);
351 for (
const auto &c : {AV_PIX_FMT_P010LE,
357 if (c == AV_PIX_FMT_P210LE) {
361 std::for_each(in.begin(), in.end(), [&](uint32_t & c) { c = dist(rand_gen); });
363 std::for_each(in.begin(), in.begin() + linesize /
sizeof(uint32_t), [&](uint32_t & c) { c = dist(rand_gen); });
364 for (
int i = 1; i < height; ++i) {
365 std::copy(in.begin(), in.begin() + linesize /
sizeof(uint32_t), in.begin() + linesize /
sizeof(uint32_t) * i);
371 assert(from_conv !=
nullptr);
372 assert(to_conv !=
nullptr);
374 struct AVFrame *converted =
to_lavc_vid_conv(from_conv, (
char *) in.data());
379 if (getenv(
"DEBUG_DUMP") !=
nullptr) {
380 for (
int i = 0; i < 128; i += 1) {
381 auto *din =
reinterpret_cast<uint32_t *
>(in.data()) + i * 4;
382 auto *dout =
reinterpret_cast<uint32_t *
>(out.data()) + i * 4;
383 printf(
"0x%08x IN =%08x %08x %08x %08x\n", i * 16, din[0], din[1], din[2], din[3]);
384 printf(
"0x%08x OUT=%08x %08x %08x %08x\n", i * 16, dout[0], dout[1], dout[2], dout[3]);
389 out[(width / 2) * height] = 123;
390 ASSERT_MESSAGE(
"Error: output matches input but it shouldn't"s, in != out);
int vc_get_linesize(unsigned int width, codec_t codec)
static __device__ vec2 abs(const vec2 &v)
av_to_uv_convert_t * get_av_to_uv_conversion(int av_codec, codec_t uv_codec)
void av_to_uv_conversion_destroy(av_to_uv_convert_t **s)
void av_to_uv_convert(const av_to_uv_convert_t *convert, char *dst, AVFrame *in, int width, int height, int pitch, const int rgb_shift[3])
static void vc_copyliner10k(unsigned char *__restrict dst, const unsigned char *__restrict src, int len, int rshift, int gshift, int bshift)
Converts from R10k to RGBA.
static void vc_copylineRGBAtoR10k(unsigned char *__restrict dst, const unsigned char *__restrict src, int dst_len, int rshift, int gshift, int bshift)
decoder_t get_decoder_from_to(codec_t in, codec_t out)
decoder_func_t * decoder_t
void to_lavc_vid_conv_destroy(struct to_lavc_vid_conv **s_p)
struct AVFrame * to_lavc_vid_conv(struct to_lavc_vid_conv *s, char *in_data)
struct to_lavc_vid_conv * to_lavc_vid_conv_init(codec_t in_pixfmt, int width, int height, enum AVPixelFormat out_pixfmt, int thread_count)
double tv_diff(struct timeval curr_time, struct timeval prev_time)
@ R10k
RGB 10-bit packed - RGBX, big-endian (2 bit padding)
@ RGB
RGB 8-bit (packed into 24-bit word)
@ RG48
16-bit RGB little-endian (RlRhGl...)
@ R12L
RGB 12-bit packed, little-endian.
@ RGBA
RGBA 8-bit, big-endian.
@ v210
YCbCr 422 10-bit - xVY0U|xY2UY1|xUY3V|xY5VY4, little-endian (2 bit padding /'x'/),...
#define ASSERT_MESSAGE(msg, expr)
size_t vc_get_datalen(unsigned int width, unsigned int height, codec_t codec)