From 5b0c8ca2682bbd6b4f0e226a3eb7d8a5ad577793 Mon Sep 17 00:00:00 2001 From: Martin Pulec Date: Wed, 25 May 2022 13:29:09 +0200 Subject: [PATCH] video pattern generator: add full-depth Y216/Y416 --- src/utils/video_pattern_generator.cpp | 12 +++++-- src/video_capture/testcard_common.c | 2 +- src/video_codec.c | 50 +++++++++++++++++++++++++++ 3 files changed, 61 insertions(+), 3 deletions(-) diff --git a/src/utils/video_pattern_generator.cpp b/src/utils/video_pattern_generator.cpp index d02e18600..33e92c6f6 100644 --- a/src/utils/video_pattern_generator.cpp +++ b/src/utils/video_pattern_generator.cpp @@ -61,6 +61,7 @@ #include #include #include +#include #include #include @@ -86,6 +87,7 @@ using std::make_unique; using std::max; using std::min; using std::move; +using std::set; using std::string; using std::swap; using std::unique_ptr; @@ -97,6 +99,8 @@ enum class generator_depth { bits16 }; +static const set native_16b{ RG48, R12L, R10k, v210, Y416, Y216 }; + class image_pattern { public: static unique_ptr create(string const & config); @@ -334,7 +338,11 @@ class image_pattern_raw : public image_pattern { unique_ptr image_pattern::create(string const &config) { if (config == "help") { cout << "Pattern to use, one of: " << BOLD("bars, blank, ebu_bars, gradient[=0x], gradient2, noise, raw=0xXX[YYZZ..], smpte_bars, 0x\n"); - cout << "\t\t- patterns 'gradient2' and 'noise' generate full bit-depth patterns with " << BOLD("RG48") << ", " << BOLD("R12L") << ", " << BOLD("R10k") << " and " << BOLD("v210") << "\n"; + cout << "\t\t- patterns 'gradient2' and 'noise' generate full bit-depth patterns with"; + for (auto & c : native_16b) { + cout << " " << BOLD(get_codec_name(c)); + } + cout << "\n"; cout << "\t\t- pattern 'raw' generates repeating sequence of given bytes without any color conversion\n"; cout << "\t\t- pattern 'smpte' uses the top bars from top 2 thirds only (doesn't render bottom third differently)\n"; return {}; @@ -411,7 +419,7 @@ video_pattern_generate(std::string const & config, int width, int height, codec_ auto data = generator->init(width, height, generator_depth::bits8); codec_t codec_src = RGBA; - if (color_spec == RG48 || color_spec == R12L || color_spec == R10k || color_spec == v210) { + if (native_16b.find(color_spec) != native_16b.end()) { data = generator->init(width, height, generator_depth::bits16); codec_src = RG48; } diff --git a/src/video_capture/testcard_common.c b/src/video_capture/testcard_common.c index 9e6f67ce5..8254a6d7a 100644 --- a/src/video_capture/testcard_common.c +++ b/src/video_capture/testcard_common.c @@ -113,7 +113,7 @@ static void toI420(unsigned char *out, const unsigned char *input, int width, in void testcard_convert_buffer(codec_t in_c, codec_t out_c, unsigned char *out, unsigned const char *in, int width, int height) { unsigned char *tmp_buffer = NULL; - if (out_c == I420 || out_c == YUYV || out_c == Y216 || out_c == Y416) { + if (out_c == I420 || out_c == YUYV) { decoder_t decoder = get_decoder_from_to(in_c, UYVY, true); tmp_buffer = malloc(2L * ((width + 1U) ^ 1U) * height); long in_linesize = vc_get_linesize(width, in_c); diff --git a/src/video_codec.c b/src/video_codec.c index 0d6522e41..9691033ce 100644 --- a/src/video_codec.c +++ b/src/video_codec.c @@ -2314,6 +2314,54 @@ static void vc_copylineRG48toV210(unsigned char * __restrict dst, const unsigned #undef FETCH_BLOCK } +static void vc_copylineRG48toY216(unsigned char * __restrict dst, const unsigned char * __restrict src, int dst_len, int rshift, + int gshift, int bshift) { + UNUSED(rshift); + UNUSED(gshift); + UNUSED(bshift); + assert((uintptr_t) src % 2 == 0); + assert((uintptr_t) dst % 2 == 0); + const uint16_t *in = (const void *) src; + uint16_t *d = (void *) dst; + OPTIMIZED_FOR (int x = 0; x < dst_len; x += 8) { + comp_type_t r, g, b; + comp_type_t u, v; + r = *in++; + g = *in++; + b = *in++; + *d++ = CLAMP_LIMITED_Y((RGB_TO_Y_709_SCALED(r, g, b) >> COMP_BASE) + (1<<12), 16); // Y + u = (RGB_TO_CB_709_SCALED(r, g, b) >> COMP_BASE); + v = (RGB_TO_CR_709_SCALED(r, g, b) >> COMP_BASE); + r = *in++; + g = *in++; + b = *in++; + *d++ = CLAMP_LIMITED_CBCR((u + (RGB_TO_CB_709_SCALED(r, g, b) >> COMP_BASE) / 2) + (1<<15), 16); // U + *d++ = CLAMP_LIMITED_Y((RGB_TO_Y_709_SCALED(r, g, b) >> COMP_BASE) + (1<<12), 16); // Y + *d++ = CLAMP_LIMITED_CBCR((v + (RGB_TO_CR_709_SCALED(r, g, b) >> COMP_BASE) / 2) + (1<<15), 16); // V + } +} + +static void vc_copylineRG48toY416(unsigned char * __restrict dst, const unsigned char * __restrict src, int dst_len, int rshift, + int gshift, int bshift) { + UNUSED(rshift); + UNUSED(gshift); + UNUSED(bshift); + assert((uintptr_t) src % 2 == 0); + assert((uintptr_t) dst % 2 == 0); + const uint16_t *in = (const void *) src; + uint16_t *d = (void *) dst; + OPTIMIZED_FOR (int x = 0; x < dst_len; x += 8) { + comp_type_t r, g, b; + r = *in++; + g = *in++; + b = *in++; + *d++ = CLAMP_LIMITED_CBCR((RGB_TO_CB_709_SCALED(r, g, b) >> COMP_BASE) + (1<<15), 16); + *d++ = CLAMP_LIMITED_Y((RGB_TO_Y_709_SCALED(r, g, b) >> COMP_BASE) + (1<<12), 16); + *d++ = CLAMP_LIMITED_CBCR((RGB_TO_CR_709_SCALED(r, g, b) >> COMP_BASE) + (1<<15), 16); + *d++ = 0xFFFFU; + } +} + /** * Converts BGR to RGB. * @copydetails vc_copylinev210 @@ -2658,6 +2706,8 @@ static const struct decoder_item decoders[] = { { (decoder_t) vc_copylineRG48toRGB, RG48, RGB, false }, { (decoder_t) vc_copylineRG48toUYVY, RG48, UYVY, true }, { (decoder_t) vc_copylineRG48toV210, RG48, v210, true }, + { (decoder_t) vc_copylineRG48toY216, RG48, Y216, true }, + { (decoder_t) vc_copylineRG48toY416, RG48, Y416, true }, { vc_copylineRGBA, RGBA, RGBA, false }, { (decoder_t) vc_copylineDVS10toV210, DVS10, v210, false }, { (decoder_t) vc_copylineRGBAtoRGB, RGBA, RGB, false },