From edad146aebc74ce7e4075c82ef24dbf44249e8bf Mon Sep 17 00:00:00 2001 From: Martin Pulec Date: Mon, 15 Aug 2022 13:35:19 +0200 Subject: [PATCH] added testcard pattern uv_plane --- src/color.h | 7 +++-- src/utils/video_pattern_generator.cpp | 43 ++++++++++++++++++++++----- 2 files changed, 40 insertions(+), 10 deletions(-) diff --git a/src/color.h b/src/color.h index 8b3856809..889c659ff 100644 --- a/src/color.h +++ b/src/color.h @@ -90,12 +90,15 @@ static_assert(sizeof(comp_type_t) * 8 >= COMP_BASE + 18, "comp_type_t not wide e #define RGB_TO_Y_709_SCALED(r, g, b) ((r) * Y_R + (g) * Y_G + (b) * Y_B) #define RGB_TO_CB_709_SCALED(r, g, b) ((r) * CB_R + (g) * CB_G + (b) * CB_B) #define RGB_TO_CR_709_SCALED(r, g, b) ((r) * CR_R + (g) * CR_G + (b) * CR_B) +#define LIMIT_LO(depth) (1<<((depth)-4)) +#define LIMIT_HI_Y(depth) (235 * (1<<((depth)-8))) +#define LIMIT_HI_CBCR(depth) (240 * (1<<((depth)-8))) #ifdef YCBCR_FULL #define CLAMP_LIMITED_Y(val, depth) (val) #define CLAMP_LIMITED_CBCR(val, depth) (val) #else -#define CLAMP_LIMITED_Y(val, depth) CLAMP((val), 1<<(depth-4), 235 * (1<<(depth-8))) -#define CLAMP_LIMITED_CBCR(val, depth) CLAMP((val), 1<<(depth-4), 240 * (1<<(depth-8))) +#define CLAMP_LIMITED_Y(val, depth) CLAMP((val), LIMIT_LO(depth), LIMIT_HI_Y(depth)) +#define CLAMP_LIMITED_CBCR(val, depth) CLAMP((val), 1<<(depth-4), LIMIT_HI_CBCR(depth)) #endif #define R_CB(kr,kb) 0.0 diff --git a/src/utils/video_pattern_generator.cpp b/src/utils/video_pattern_generator.cpp index 18d85705a..4d52ac935 100644 --- a/src/utils/video_pattern_generator.cpp +++ b/src/utils/video_pattern_generator.cpp @@ -64,6 +64,7 @@ #include #include +#include "color.h" #include "debug.h" #include "ug_runtime_error.hpp" #include "utils/color_out.h" @@ -318,7 +319,7 @@ class image_pattern_gradient2 : public image_pattern { private: const unsigned int val_max; enum generator_depth fill(int width, int height, unsigned char *data) override { - width = max(width, 2); // avoid division by zero + assert(width > 1); // avoid division by zero auto *ptr = reinterpret_cast(data); for (int j = 0; j < height; j += 1) { for (int i = 0; i < width; i += 1) { @@ -332,6 +333,35 @@ class image_pattern_gradient2 : public image_pattern { } }; +class image_pattern_uv_plane : public image_pattern { + public: + explicit image_pattern_uv_plane(string &y_lvl) { + if (!y_lvl.empty()) { + y_level = LIMIT_LO(16) + stof(y_lvl) * (LIMIT_LO(16) + LIMIT_HI_Y(16)); + } + } + private: + int y_level = LIMIT_HI_Y(16); + enum generator_depth fill(int width, int height, unsigned char *data) override { + assert(width > 1 && height > 1); // avoid division by zero + auto *ptr = reinterpret_cast(data); + auto *conv = get_decoder_from_to(Y416, RG48); + int scale_cbcr = LIMIT_HI_CBCR(16) - LIMIT_LO(16); + for (int j = 0; j < height; j += 1) { + for (int i = 0; i < width; i += 1) { + uint16_t uyva[4]; + uyva[0] = LIMIT_LO(16) + i * scale_cbcr / (width - 1); + uyva[1] = y_level; + uyva[2] = LIMIT_LO(16) + j * scale_cbcr / (height - 1); + uyva[3] = 0xFF'FF; + conv((unsigned char *) ptr, (unsigned char *) uyva, 6, DEFAULT_R_SHIFT, DEFAULT_G_SHIFT, DEFAULT_B_SHIFT); + ptr += 3; + } + } + return generator_depth::bits16; + } +}; + class image_pattern_noise : public image_pattern { default_random_engine rand_gen; enum generator_depth fill(int width, int height, unsigned char *data) override { @@ -414,6 +444,9 @@ unique_ptr image_pattern::create(string const &config) { if (config == "smpte_bars") { return make_unique(); } + if (pattern == "uv_plane") { + return make_unique(params); + } if (config.substr(0, "0x"s.length()) == "0x") { uint32_t blank_color = 0U; if (sscanf(config.substr("0x"s.length()).c_str(), "%x", &blank_color) == 1) { @@ -530,13 +563,8 @@ video_pattern_generator_t video_pattern_generator_create(std::string const & config, int width, int height, codec_t color_spec, int offset) { if (config == "help") { -<<<<<<< Updated upstream - col() << "Pattern to use, one of: " << TBOLD("bars, blank, ebu_bars, gradient[=0x], gradient2, gray, noise, raw=0xXX[YYZZ..], smpte_bars, 0x\n"); - col() << "\t\t- patterns " TBOLD("'gradient2'") " and " TBOLD("'noise'") " generate full bit-depth patterns with"; -======= - col() << "Pattern to use, one of: " << TBOLD("bars, blank[=0x], ebu_bars, gradient[=0x], gradient2*, gray, noise, raw=0xXX[YYZZ..], smpte_bars, uv_plane[=]\n"); + col() << "Pattern to use, one of: " << TBOLD("bars, blank, ebu_bars, gradient[=0x], gradient2*, gray, noise, raw=0xXX[YYZZ..], smpte_bars, uv_plane[=], 0x\n"); col() << "\t\t- patterns " TBOLD("'gradient2'") ", " TBOLD("'noise'") " and " TBOLD("'uv_plane'") " generate full bit-depth patterns with"; ->>>>>>> Stashed changes for (codec_t c = VIDEO_CODEC_FIRST; c != VIDEO_CODEC_COUNT; c = static_cast(static_cast(c) + 1)) { if (get_decoder_from_to(RG48, c) != NULL) { col() << " " << TERM_BOLD << get_codec_name(c) << TERM_RESET; @@ -544,7 +572,6 @@ video_pattern_generator_create(std::string const & config, int width, int height } col() << "\n"; col() << "\t\t- pattern " << TBOLD("'raw'") " generates repeating sequence of given bytes without any color conversion\n"; - col() << "\t\t- patterns marked with " << TBOLD("'*'") " provide help as its option\n"; return nullptr; } assert(width > 0 && height > 0);