#include "PixelFormat.hpp" #include #include #include #include #include namespace { struct YCbCr10 { uint32_t y; uint32_t cb; uint32_t cr; }; struct BarSpec { const char* name; RgbColor rgb75; }; const BarSpec bars[] = { {"White", {191, 191, 191}}, {"Yellow", {191, 191, 0}}, {"Cyan", { 0, 191, 191}}, {"Green", { 0, 191, 0}}, {"Magenta", {191, 0, 191}}, {"Red", {191, 0, 0}}, {"Blue", { 0, 0, 191}}, {"Black", { 0, 0, 0}}, }; YCbCr10 rgbToYCbCr10(RgbColor rgb) { double r = rgb.r / 255.0; double g = rgb.g / 255.0; double b = rgb.b / 255.0; double y = 0.2126 * r + 0.7152 * g + 0.0722 * b; double cb = -0.1146 * r - 0.3854 * g + 0.5000 * b; double cr = 0.5000 * r - 0.4542 * g - 0.0458 * b; uint32_t y10 = static_cast(std::round(y * 876.0 + 64.0)); uint32_t cb10 = static_cast(std::round(cb * 896.0 + 512.0)); uint32_t cr10 = static_cast(std::round(cr * 896.0 + 512.0)); return {y10, cb10, cr10}; } void encodeV210Line( const YCbCr10* pixels, uint32_t width, uint8_t* out) { uint32_t groups = (width + 5) / 6; for (uint32_t g = 0; g < groups; ++g) { uint32_t cb0 = (g * 6 + 0 < width) ? pixels[g * 6 + 0].cb : pixels[width - 1].cb; uint32_t y0 = (g * 6 + 0 < width) ? pixels[g * 6 + 0].y : pixels[width - 1].y; uint32_t cr0 = (g * 6 + 0 < width) ? pixels[g * 6 + 0].cr : pixels[width - 1].cr; uint32_t y1 = (g * 6 + 1 < width) ? pixels[g * 6 + 1].y : pixels[width - 1].y; uint32_t cb2 = (g * 6 + 2 < width) ? pixels[g * 6 + 2].cb : pixels[width - 1].cb; uint32_t y2 = (g * 6 + 2 < width) ? pixels[g * 6 + 2].y : pixels[width - 1].y; uint32_t cr2 = (g * 6 + 3 < width) ? pixels[g * 6 + 3].cr : pixels[width - 1].cr; uint32_t y3 = (g * 6 + 3 < width) ? pixels[g * 6 + 3].y : pixels[width - 1].y; uint32_t cb4 = (g * 6 + 4 < width) ? pixels[g * 6 + 4].cb : pixels[width - 1].cb; uint32_t y4 = (g * 6 + 4 < width) ? pixels[g * 6 + 4].y : pixels[width - 1].y; uint32_t cr4 = (g * 6 + 5 < width) ? pixels[g * 6 + 5].cr : pixels[width - 1].cr; uint32_t y5 = (g * 6 + 5 < width) ? pixels[g * 6 + 5].y : pixels[width - 1].y; uint32_t w0 = (cb0 & 0x3FF) | ((y0 & 0x3FF) << 10) | ((cr0 & 0x3FF) << 20); uint32_t w1 = (y1 & 0x3FF) | ((cb2 & 0x3FF) << 10) | ((y2 & 0x3FF) << 20); uint32_t w2 = (cr2 & 0x3FF) | ((y3 & 0x3FF) << 10) | ((cb4 & 0x3FF) << 20); uint32_t w3 = (y4 & 0x3FF) | ((cr4 & 0x3FF) << 10) | ((y5 & 0x3FF) << 20); uint8_t* p = out + g * 16; p[0] = static_cast(w0); p[1] = static_cast(w0 >> 8); p[2] = static_cast(w0 >> 16); p[3] = static_cast(w0 >> 24); p[4] = static_cast(w1); p[5] = static_cast(w1 >> 8); p[6] = static_cast(w1 >> 16); p[7] = static_cast(w1 >> 24); p[8] = static_cast(w2); p[9] = static_cast(w2 >> 8); p[10] = static_cast(w2 >> 16); p[11] = static_cast(w2 >> 24); p[12] = static_cast(w3); p[13] = static_cast(w3 >> 8); p[14] = static_cast(w3 >> 16); p[15] = static_cast(w3 >> 24); } } } int main() { constexpr uint32_t width = 1920; constexpr uint32_t height = 1; constexpr uint32_t dstWidth = 512; constexpr uint32_t dstHeight = 1; uint32_t groups = (width + 5) / 6; uint32_t stride = ((groups * 16 + 127) / 128) * 128; printf("v210 conversion test\n"); printf("width=%u stride=%u\n", width, stride); std::vector line(width); for (uint32_t x = 0; x < width; ++x) { size_t bar = (x * 8) / width; if (bar > 7) bar = 7; line[x] = rgbToYCbCr10(bars[bar].rgb75); } printf("\nReference YCbCr values:\n"); for (size_t i = 0; i < 8; ++i) { YCbCr10 ref = rgbToYCbCr10(bars[i].rgb75); printf(" %-10s Y=%4u Cb=%4u Cr=%4u\n", bars[i].name, ref.y, ref.cb, ref.cr); } std::vector v210Data(stride, 0); encodeV210Line(line.data(), width, v210Data.data()); std::vector rgbaBuf(dstWidth * dstHeight, 0); convertV210ToRgba( v210Data.data(), width, height, stride, rgbaBuf.data(), dstWidth, dstHeight); printf("\nDecode results:\n"); int totalErrors = 0; for (size_t i = 0; i < 8; ++i) { uint32_t x = (i * dstWidth) / 8 + dstWidth / 16; if (x >= dstWidth) x = dstWidth - 1; uint32_t pixel = rgbaBuf[x]; uint8_t r = static_cast(pixel & 0xFF); uint8_t g = static_cast((pixel >> 8) & 0xFF); uint8_t b = static_cast((pixel >> 16) & 0xFF); RgbColor expected = bars[i].rgb75; int dr = static_cast(r) - static_cast(expected.r); int dg = static_cast(g) - static_cast(expected.g); int db = static_cast(b) - static_cast(expected.b); bool ok = (dr >= -3 && dr <= 3 && dg >= -3 && dg <= 3 && db >= -3 && db <= 3); if (!ok) totalErrors++; printf(" %-10s: got (%3u,%3u,%3u) expected (%3u,%3u,%3u) delta=(%+d,%+d,%+d) %s\n", bars[i].name, r, g, b, expected.r, expected.g, expected.b, dr, dg, db, ok ? "OK" : "FAIL"); } printf("\n%d bar(s) out of tolerance\n", totalErrors); return totalErrors > 0 ? 1 : 0; }