From 170c50f7ab2006de28efe025d79368d099b18afc Mon Sep 17 00:00:00 2001 From: Martin Pulec Date: Fri, 21 Apr 2023 15:10:35 +0200 Subject: [PATCH] testcard: added interlaced pattern --- src/utils/video_pattern_generator.cpp | 58 ++++++++++++++++++++++++++- 1 file changed, 57 insertions(+), 1 deletion(-) diff --git a/src/utils/video_pattern_generator.cpp b/src/utils/video_pattern_generator.cpp index ee21fc0a1..845321419 100644 --- a/src/utils/video_pattern_generator.cpp +++ b/src/utils/video_pattern_generator.cpp @@ -631,11 +631,64 @@ private: vector> data; }; +struct interlaced_video_pattern_generator : public video_pattern_generator { + interlaced_video_pattern_generator(int w, int h, codec_t color_spec) + : width(w), height(h), linesize(vc_get_linesize(width, color_spec)) + { + size_t rgb_linesize = vc_get_linesize(width, RGB); + vector rgb(3 * h * rgb_linesize + 4 * (width / step) * rgb_linesize); + memset(rgb.data(), 255, h * rgb_linesize); + char *ptr = rgb.data() + h * rgb_linesize; + auto fill = [&](int col1, int col2) { + for (int i = 0; i < width; i += step) { + size_t fill_len = rgb_linesize - i * 3; + memset(ptr, col1, fill_len); + memset(ptr + fill_len, col2, rgb_linesize - fill_len); + ptr += rgb_linesize; + fill_len = MAX(0, (int) rgb_linesize - (i + 2 * step) * 3); + memset(ptr, col1, fill_len); + memset(ptr + fill_len, col2, rgb_linesize - fill_len); + ptr += rgb_linesize; + } + }; + fill(255, 0); + memset(ptr, 0, h * rgb_linesize); + ptr += h * rgb_linesize; + fill(0, 255); + memset(ptr, 255, h * rgb_linesize); + vector rgba(rgb.size() / 3 * 4); + for (unsigned i = 0; i < rgb.size(); i += 3) { + rgba[i / 3 * 4] = rgb[i]; + rgba[i / 3 * 4 + 1] = rgb[i + 1]; + rgba[i / 3 * 4 + 2] = rgb[i + 2]; + rgba[i / 3 * 4 + 3] = 0xff; + } + data.resize(3 * h * linesize + 4 * linesize * (w / step)); + testcard_convert_buffer(RGBA, color_spec, (unsigned char *) data.data(), (unsigned char *) rgba.data(), width, 3 * height + 4 * (width / step)); + } + char *get_next() override { + auto *out = (char *) data.data() + cur_idx * linesize; + cur_idx += 8; + if (cur_idx >= 2 * height + 4 * width / step) { + cur_idx = 0; + } + + return out; + } +private: + constexpr static int step = 3; + int width; + int height; + size_t linesize; + int cur_idx = 0; + vector data; +}; + 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") { - col() << "Pattern to use, one of: " << SBOLD("bars, blank[=0x], ebu_bars, gradient[=0x], gradient2*, gray, noise, raw=0xXX[YYZZ..], smpte_bars, uv_plane[=]\n"); + col() << "Pattern to use, one of: " << SBOLD("bars, blank[=0x], ebu_bars, gradient[=0x], gradient2*, gray, interlaced, noise, raw=0xXX[YYZZ..], smpte_bars, uv_plane[=]\n"); col() << "\t\t- patterns " SBOLD("'gradient'") ", " SBOLD("'gradient2'") ", " SBOLD("'noise'") " and " SBOLD("'uv_plane'") " generate higher bit-depth patterns with"; 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 && get_bits_per_component(c) > 8) { @@ -658,6 +711,9 @@ video_pattern_generator_create(std::string const & config, int width, int height if (pattern == "gray" || pattern == "grey") { return new gray_video_pattern_generator{width, height, color_spec, params.c_str()}; } + if (pattern == "interlaced") { + return new interlaced_video_pattern_generator{width, height, color_spec}; + } return new still_image_video_pattern_generator{pattern, params, width, height, color_spec, offset}; } catch (exception const &e) { LOG(LOG_LEVEL_ERROR) << MOD_NAME << e.what() << "\n";