From 2db8fa4f8ef136f8fc642f9bf0080df7254c96bd Mon Sep 17 00:00:00 2001 From: Nathoufresh <39437515+Nathoufresh@users.noreply.github.com> Date: Fri, 26 Jul 2024 15:24:24 +0200 Subject: [PATCH] bgr_444_8_le_msb_support (#20) BGR4444 support --------- Co-authored-by: Nathan COLINET Co-authored-by: Julien Alofs --- CHANGELOG.md | 5 + include/videoviewer/videoviewer.hpp | 1 + sample/colorbar.cpp | 722 +++++++++++++----------- sample/colorbar.hpp | 153 ++--- sample/main.cpp | 236 ++++---- src/CMakeLists.txt | 1 + src/bgr4444_8_to_rgb4444.shader | 16 + src/bgr444_8_to_rgb4444.shader | 98 ++-- src/rgb444_8_to_rgb4444.shader | 100 ++-- src/vertex.shader | 34 +- src/videoviewer_internal.cpp | 7 + src/ycbcr422_10_be_to_rgb444.shader | 194 +++---- src/ycbcr422_10_le_msb_to_rgb444.shader | 160 +++--- src/ycbcr422_8_to_rgb444.shader | 70 +-- src/ycbcr444_8_to_rgb444.shader | 128 ++--- 15 files changed, 1008 insertions(+), 917 deletions(-) create mode 100644 src/bgr4444_8_to_rgb4444.shader diff --git a/CHANGELOG.md b/CHANGELOG.md index 21191cf..84456d9 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,3 +1,8 @@ +## 1.2.0 + +### Added +- Add support for BGR 4:4:4:4 8bits (little endian + padding) [Issue #19, PR !20] + ## 1.1.2 ### Fixes diff --git a/include/videoviewer/videoviewer.hpp b/include/videoviewer/videoviewer.hpp index 3b14180..d07145c 100644 --- a/include/videoviewer/videoviewer.hpp +++ b/include/videoviewer/videoviewer.hpp @@ -56,6 +56,7 @@ namespace Deltacast reserved_bgr_444_12_be, /*< BGR 4:4:4 12bit big endian without any padding */ reserved_bgr_444_16_le, /*< BGR 4:4:4 16bit little endian without any padding */ reserved_bgr_444_16_be, /*< BGR 4:4:4 12bit big endian without any padding */ + bgr_444_8_le_msb, /*< BGR 4:4:4 8bit with msb padding (32 bits) */ nb_input_format }; diff --git a/sample/colorbar.cpp b/sample/colorbar.cpp index c2263a2..353f8ad 100644 --- a/sample/colorbar.cpp +++ b/sample/colorbar.cpp @@ -1,333 +1,389 @@ -/* - * SPDX-FileCopyrightText: Copyright (c) DELTACAST.TV. All rights reserved. - * SPDX-License-Identifier: Apache-2.0 - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -#include "colorbar.hpp" - -using namespace Deltacast; - -// This structure is used to store the YUV 4:2:2 10bit little endian color bar pattern in memory -typedef struct -{ - uint32_t part_0; - uint32_t part_1; - uint32_t part_2; - uint32_t part_3; -}DataV210; - - -// This structure is used to store the YUV 4:2:2 10bit Big Endian color bar pattern in memory -typedef struct -{ - uint8_t part_0; - uint8_t part_1; - uint8_t part_2; - uint8_t part_3; - uint8_t part_4; -}DataYUV42210BE; - - -#define V208_WHITE75 0xB480B480 -#define V208_YELLOW75 0xA888A82C -#define V208_CYAN75 0x912C9193 -#define V208_GREEN75 0x8534853F -#define V208_MAGENTA75 0x3FCC3FC1 -#define V208_RED75 0x33D4336D -#define V208_BLUE75 0x1C781CD4 -#define V208_BLACK75 0x10801080 -#define V208_MINUSI 0x3D633D99 -#define V208_PLUSQ 0x239823AE -#define V208_WHITE100 0xEB80EB80 -#define V208_BLACKMINUS2 0x0C800C80 -#define V208_BLACKPLUS2 0x14801480 - -#define V210_HD_WHITE75 {0x200B4200,0x2D0802D0,0x200B4200,0x2D0802D0} /* 6 pixels */ -#define V210_HD_YELLOW75 {0x220A80B0,0x2A02C2A0,0x0B0A8220,0x2A0882A0} /* 6 pixels */ -#define V210_HD_CYAN75 {0x0B09124C,0x24493244,0x24C910B0,0x2442C244} /* 6 pixels */ -#define V210_HD_GREEN75 {0x0D0850FC,0x2143D214,0x0FC850D0,0x21434214} /* 6 pixels */ -#define V210_HD_MAGENTA75 {0x3303F304,0x0FCC10FC,0x3043F330,0x0FCCC0FC} /* 6 pixels */ -#define V210_HD_RED75 {0x350331B4,0x0CC6D0CC,0x1B433350,0x0CCD40CC} /* 6 pixels */ -#define V210_HD_BLUE75 {0x1E01C350,0x070D4070,0x3501C1E0,0x07078070} /* 6 pixels */ -#define V210_HD_BLACK75 {0x20010200,0x04080040,0x20010200,0x04080040} /* 6 pixels */ - -#define Y444_WHITE100_Q 0x0080EB80 //0x80EA80 0x VV YY UU -#define Y444_YELLOW100_Q 0x008ADB10 //0x8ADA10 -#define Y444_CYAN100_Q 0x0010BC9A //0x10BC9A -#define Y444_GREEN100_Q 0x001AAD2A //0x1BAC2A -#define Y444_MAGENTA100_Q 0x00E64ED6 //0xE54ED6 -#define Y444_RED100_Q 0x00F03F66 //0xF03E66 -#define Y444_BLUE100_Q 0x007620F0 //0x7620F0 -#define Y444_BLACK100_Q 0x00801080 //0x801080 - -#define YUV42210BE_WHITE_100 {0x80,0x3A,0xB8,0x03,0xAC} /* 2 pixels - 5 bytes */ -#define YUV42210BE_YELLOW_100 {0x10,0x36,0xB8,0x2B,0xAC} /* 2 pixels - 5 bytes */ -#define YUV42210BE_CYAN_100 {0x99,0x6F,0xC1,0x42,0xF0} /* 2 pixels - 5 bytes */ -#define YUV42210BE_GREEN_100 {0x29,0x6B,0xC1,0x6A,0xB0} /* 2 pixels - 5 bytes */ -#define YUV42210BE_MAGENTA_100 {0xD6,0x93,0xEE,0x95,0x38} /* 2 pixels - 5 bytes */ -#define YUV42210BE_RED_100 {0x66,0x8F,0xEE,0xBC,0xF8} /* 2 pixels - 5 bytes */ -#define YUV42210BE_BLACK_100 {0x80,0x04,0x08,0x00,0x40} /* 2 pixels - 5 bytes */ -#define YUV42210BE_BLUE_100 {0xEF,0xC7,0xF7,0xD4,0x7C} /* 2 pixels - 5 bytes */ - -#define R444_WHITE100_Q 0x00FFFFFF //0xFFFFFF 0x BB GG RR -#define R444_YELLOW100_Q 0x0000FFFF //0x00FFFF -#define R444_CYAN100_Q 0x00FFFF00 //0xFFFF00 -#define R444_GREEN100_Q 0x0000FF00 //0x00FF00 -#define R444_MAGENTA100_Q 0x00FF00FF //0xFF00FF -#define R444_RED100_Q 0x000000FF //0x0000FF -#define R444_BLUE100_Q 0x00FF0000 //0xFF0000 -#define R444_BLACK100_Q 0x00000000 //0x000000 - -ColorBar::ColorBar(int width, int height, PixelFormat pixel_format): - m_pixel_format(pixel_format) - ,m_width(width) - ,m_height(height) -{ - switch (pixel_format) - { - case PixelFormat::ycbcr_422_8: - init_ycbcr422_8(width, height); - break; - case PixelFormat::ycbcr_422_10_le_msb: - init_ycbcr_422_10_le_msb(width, height); - break; - case PixelFormat::ycbcr_444_8: - init_ycbcr_444_8(width, height); - break; - case PixelFormat::ycbcr_422_10_be: - init_ycbcr_422_10_be(width, height); - break; - case PixelFormat::rgb_444_8: - init_rgb_444_8(width, height); - break; - default: break; - } -} - -ColorBar::~ColorBar() -{ - if(m_pattern) - delete[] m_pattern; -} - -uint8_t* ColorBar::get_data() -{ - return m_pattern; -} - -uint64_t ColorBar::get_datasize() -{ - return m_datasize; -} - -void ColorBar::init_ycbcr_422_10_le_msb(int width, int height) -{ - DataV210 color[] = { V210_HD_WHITE75,V210_HD_YELLOW75,V210_HD_CYAN75,V210_HD_GREEN75,V210_HD_MAGENTA75,V210_HD_RED75,V210_HD_BLUE75,V210_HD_BLACK75 }; - m_datasize = width * height * 8 / 3; - m_pattern = new uint8_t[m_datasize]; - if (m_pattern) - { - DataV210* pData_X = (DataV210*)m_pattern; - - for (int pixel = 0; pixel < width * height; pixel += 6) - { - *pData_X = color[(pixel % width) / (width / 8)]; - pData_X++; - } - } -} - -void ColorBar::init_ycbcr_422_10_be(int width, int height) -{ - DataYUV42210BE color[] = { YUV42210BE_WHITE_100, YUV42210BE_YELLOW_100 , YUV42210BE_CYAN_100 , YUV42210BE_GREEN_100 , YUV42210BE_MAGENTA_100, YUV42210BE_RED_100 , YUV42210BE_BLUE_100, YUV42210BE_BLACK_100 }; - m_datasize = width * height * 5 / 2; - m_pattern = new uint8_t[m_datasize]; - if (m_pattern) - { - DataYUV42210BE* pData_X = (DataYUV42210BE*)m_pattern; - for (int pixel = 0; pixel < width * height; pixel += 2) - { - *pData_X = color[(pixel % width) / (width / 8)]; - pData_X++; - } - } -} -void ColorBar::init_ycbcr422_8(int width, int height) -{ - m_datasize = (uint64_t)width * height * 2; - m_pattern = new uint8_t[m_datasize]; - - for (uint64_t x = 0; x < width; x += 2) - { - for (uint64_t y = 0; y < height; y++) - { - if (x < 1 * (width / 8)) - *(uint32_t*)(m_pattern + (x * 2) + (y * width * 2)) = V208_WHITE75; - else if (x < 2 * (width / 8)) - *(uint32_t*)(m_pattern + (x * 2) + (y * width * 2)) = V208_YELLOW75; - else if (x < 3 * (width / 8)) - *(uint32_t*)(m_pattern + (x * 2) + (y * width * 2)) = V208_CYAN75; - else if (x < 4 * (width / 8)) - *(uint32_t*)(m_pattern + (x * 2) + (y * width * 2)) = V208_GREEN75; - else if (x < 5 * (width / 8)) - *(uint32_t*)(m_pattern + (x * 2) + (y * width * 2)) = V208_MAGENTA75; - else if (x < 6 * (width / 8)) - *(uint32_t*)(m_pattern + (x * 2) + (y * width * 2)) = V208_RED75; - else if (x < 7 * (width / 8)) - *(uint32_t*)(m_pattern + (x * 2) + (y * width * 2)) = V208_BLUE75; - else if (x < 8 * (width / 8)) - *(uint32_t*)(m_pattern + (x * 2) + (y * width * 2)) = V208_BLACK75; - } - } -} - -void ColorBar::init_ycbcr_444_8(int width, int height) -{ - m_datasize = (uint64_t)width * height * 3; - m_pattern = new uint8_t[m_datasize]; - - for (uint64_t x = 0; x < width-1; x++) - { - for (uint64_t y = 0; y < height; y++) - { - if (x < 1 * (width / 8)) - *(uint32_t*)(m_pattern + (x * 3) + (y * width * 3)) = Y444_WHITE100_Q; - else if (x < 2 * (width / 8)) - *(uint32_t*)(m_pattern + (x * 3) + (y * width * 3)) = Y444_YELLOW100_Q; - else if (x < 3 * (width / 8)) - *(uint32_t*)(m_pattern + (x * 3) + (y * width * 3)) = Y444_CYAN100_Q; - else if (x < 4 * (width / 8)) - *(uint32_t*)(m_pattern + (x * 3) + (y * width * 3)) = Y444_GREEN100_Q; - else if (x < 5 * (width / 8)) - *(uint32_t*)(m_pattern + (x * 3) + (y * width * 3)) = Y444_MAGENTA100_Q; - else if (x < 6 * (width / 8)) - *(uint32_t*)(m_pattern + (x * 3) + (y * width * 3)) = Y444_RED100_Q; - else if (x < 7 * (width / 8)) - *(uint32_t*)(m_pattern + (x * 3) + (y * width * 3)) = Y444_BLUE100_Q; - else if (x < 8 * (width / 8)) - *(uint32_t*)(m_pattern + (x * 3) + (y * width * 3)) = Y444_BLACK100_Q; - } - } - -} - -void ColorBar::init_rgb_444_8(int width, int height) -{ - m_datasize = (uint64_t)width * height * 3; - m_pattern = new uint8_t[m_datasize]; - - for (uint64_t x = 0; x < width-1; x++) - { - for (uint64_t y = 0; y < height; y++) - { - if (x < 1 * (width / 8)) - *(uint32_t*)(m_pattern + (x * 3) + (y * width * 3)) = R444_WHITE100_Q; - else if (x < 2 * (width / 8)) - *(uint32_t*)(m_pattern + (x * 3) + (y * width * 3)) = R444_YELLOW100_Q; - else if (x < 3 * (width / 8)) - *(uint32_t*)(m_pattern + (x * 3) + (y * width * 3)) = R444_CYAN100_Q; - else if (x < 4 * (width / 8)) - *(uint32_t*)(m_pattern + (x * 3) + (y * width * 3)) = R444_GREEN100_Q; - else if (x < 5 * (width / 8)) - *(uint32_t*)(m_pattern + (x * 3) + (y * width * 3)) = R444_MAGENTA100_Q; - else if (x < 6 * (width / 8)) - *(uint32_t*)(m_pattern + (x * 3) + (y * width * 3)) = R444_RED100_Q; - else if (x < 7 * (width / 8)) - *(uint32_t*)(m_pattern + (x * 3) + (y * width * 3)) = R444_BLUE100_Q; - else if (x < 8 * (width / 8)) - *(uint32_t*)(m_pattern + (x * 3) + (y * width * 3)) = R444_BLACK100_Q; - } - } - -} - -void ColorBar::draw_moving_line(uint8_t* data, int frame_count) -{ - switch (m_pixel_format) - { - case PixelFormat::ycbcr_422_8: - draw_moving_line_ycbcr_422_8(data, frame_count); - break; - case PixelFormat::ycbcr_422_10_le_msb: - draw_moving_line_ycbcr_422_10_le_msb(data, frame_count); - break; - case PixelFormat::ycbcr_444_8: - draw_moving_line_ycbcr_444_8(data, frame_count); - break; - case PixelFormat::ycbcr_422_10_be: - draw_moving_line_ycbcr_422_10_be(data, frame_count); - break; - case PixelFormat::rgb_444_8: - draw_moving_line_rgb_444_8(data, frame_count); - break; - default: break; - } -} - -void ColorBar::draw_moving_line_ycbcr_422_8(uint8_t* data, int frame_count) -{ - for(uint64_t x = 0; x < m_width; x += 2) - *(uint32_t*)(data + (x * 2) + ((uint64_t)frame_count%m_height) * m_width * 2) = V208_WHITE75; -} - -void ColorBar::draw_moving_line_ycbcr_422_10_le_msb(uint8_t* data, int frame_count) -{ - int line = frame_count % m_height; - - if (line * m_width * 8 % 3 == 0) - { - DataV210* pData_X = (DataV210*)(data + line * m_width * 8 / 3); - for (int x = 0; x < m_width; x += 6) - { - *pData_X = V210_HD_WHITE75; - pData_X++; - } - } - else - { - int pxl = line * m_width; - pxl += (6 - pxl % 6); - - DataV210* pData_X = (DataV210*)(data + pxl*8/3); - - for (int x = 0; x < m_width-6; x += 6) - { - *pData_X = V210_HD_WHITE75; - pData_X++; - } - } - - -} -void ColorBar::draw_moving_line_ycbcr_422_10_be(uint8_t* data, int frame_count) -{ - DataYUV42210BE* pData_X = (DataYUV42210BE*)(data + frame_count % m_height * m_width * 5 / 2); - for (int x = 0; x < m_width; x += 2) - { - *pData_X = YUV42210BE_WHITE_100; - pData_X++; - } - -} - -void ColorBar::draw_moving_line_ycbcr_444_8(uint8_t* data, int frame_count) -{ - for (uint64_t x = 0; x < (m_width-1); x++) - *(uint32_t*)(data + (x * 3) + ((uint64_t)frame_count % m_height) * m_width * 3) = Y444_WHITE100_Q; -} - -void ColorBar::draw_moving_line_rgb_444_8(uint8_t* data, int frame_count) -{ - for (uint64_t x = 0; x < (m_width-1); x++) - *(uint32_t*)(data + (x * 3) + ((uint64_t)frame_count % m_height) * m_width * 3) = R444_WHITE100_Q; -} \ No newline at end of file +/* + * SPDX-FileCopyrightText: Copyright (c) DELTACAST.TV. All rights reserved. + * SPDX-License-Identifier: Apache-2.0 + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include +#include +#include "colorbar.hpp" + +using namespace Deltacast; + +// This structure is used to store the YUV 4:2:2 10bit little endian color bar pattern in memory +typedef struct +{ + uint32_t part_0; + uint32_t part_1; + uint32_t part_2; + uint32_t part_3; +}DataV210; + + +// This structure is used to store the YUV 4:2:2 10bit Big Endian color bar pattern in memory +typedef struct +{ + uint8_t part_0; + uint8_t part_1; + uint8_t part_2; + uint8_t part_3; + uint8_t part_4; +}DataYUV42210BE; + + +#define V208_WHITE75 0xB480B480 +#define V208_YELLOW75 0xA888A82C +#define V208_CYAN75 0x912C9193 +#define V208_GREEN75 0x8534853F +#define V208_MAGENTA75 0x3FCC3FC1 +#define V208_RED75 0x33D4336D +#define V208_BLUE75 0x1C781CD4 +#define V208_BLACK75 0x10801080 +#define V208_MINUSI 0x3D633D99 +#define V208_PLUSQ 0x239823AE +#define V208_WHITE100 0xEB80EB80 +#define V208_BLACKMINUS2 0x0C800C80 +#define V208_BLACKPLUS2 0x14801480 + +#define V210_HD_WHITE75 {0x200B4200,0x2D0802D0,0x200B4200,0x2D0802D0} /* 6 pixels */ +#define V210_HD_YELLOW75 {0x220A80B0,0x2A02C2A0,0x0B0A8220,0x2A0882A0} /* 6 pixels */ +#define V210_HD_CYAN75 {0x0B09124C,0x24493244,0x24C910B0,0x2442C244} /* 6 pixels */ +#define V210_HD_GREEN75 {0x0D0850FC,0x2143D214,0x0FC850D0,0x21434214} /* 6 pixels */ +#define V210_HD_MAGENTA75 {0x3303F304,0x0FCC10FC,0x3043F330,0x0FCCC0FC} /* 6 pixels */ +#define V210_HD_RED75 {0x350331B4,0x0CC6D0CC,0x1B433350,0x0CCD40CC} /* 6 pixels */ +#define V210_HD_BLUE75 {0x1E01C350,0x070D4070,0x3501C1E0,0x07078070} /* 6 pixels */ +#define V210_HD_BLACK75 {0x20010200,0x04080040,0x20010200,0x04080040} /* 6 pixels */ + +#define Y444_WHITE100_Q 0x0080EB80 //0x80EA80 0x VV YY UU +#define Y444_YELLOW100_Q 0x008ADB10 //0x8ADA10 +#define Y444_CYAN100_Q 0x0010BC9A //0x10BC9A +#define Y444_GREEN100_Q 0x001AAD2A //0x1BAC2A +#define Y444_MAGENTA100_Q 0x00E64ED6 //0xE54ED6 +#define Y444_RED100_Q 0x00F03F66 //0xF03E66 +#define Y444_BLUE100_Q 0x007620F0 //0x7620F0 +#define Y444_BLACK100_Q 0x00801080 //0x801080 + +#define YUV42210BE_WHITE_100 {0x80,0x3A,0xB8,0x03,0xAC} /* 2 pixels - 5 bytes */ +#define YUV42210BE_YELLOW_100 {0x10,0x36,0xB8,0x2B,0xAC} /* 2 pixels - 5 bytes */ +#define YUV42210BE_CYAN_100 {0x99,0x6F,0xC1,0x42,0xF0} /* 2 pixels - 5 bytes */ +#define YUV42210BE_GREEN_100 {0x29,0x6B,0xC1,0x6A,0xB0} /* 2 pixels - 5 bytes */ +#define YUV42210BE_MAGENTA_100 {0xD6,0x93,0xEE,0x95,0x38} /* 2 pixels - 5 bytes */ +#define YUV42210BE_RED_100 {0x66,0x8F,0xEE,0xBC,0xF8} /* 2 pixels - 5 bytes */ +#define YUV42210BE_BLACK_100 {0x80,0x04,0x08,0x00,0x40} /* 2 pixels - 5 bytes */ +#define YUV42210BE_BLUE_100 {0xEF,0xC7,0xF7,0xD4,0x7C} /* 2 pixels - 5 bytes */ + +#define R444_WHITE100_Q 0x00FFFFFF //0xFFFFFF 0x BB GG RR +#define R444_YELLOW100_Q 0x0000FFFF //0x00FFFF +#define R444_CYAN100_Q 0x00FFFF00 //0xFFFF00 +#define R444_GREEN100_Q 0x0000FF00 //0x00FF00 +#define R444_MAGENTA100_Q 0x00FF00FF //0xFF00FF +#define R444_RED100_Q 0x000000FF //0x0000FF +#define R444_BLUE100_Q 0x00FF0000 //0xFF0000 +#define R444_BLACK100_Q 0x00000000 //0x000000 + +#define BGR444_WHITE100_Q 0x00FFFFFF // BGR: 0xFFFFFF +#define BGR444_YELLOW100_Q 0x00FFFF00 // BGR: 0xFFFF00 +#define BGR444_CYAN100_Q 0x0000FFFF // BGR: 0x00FFFF +#define BGR444_GREEN100_Q 0x0000FF00 // BGR: 0x00FF00 +#define BGR444_MAGENTA100_Q 0x00FF00FF // BGR: 0xFF00FF +#define BGR444_RED100_Q 0x00FF0000 // BGR: 0xFF0000 +#define BGR444_BLUE100_Q 0x000000FF // BGR: 0x0000FF +#define BGR444_BLACK100_Q 0x00000000 // BGR: 0x000000 + + +ColorBar::ColorBar(int width, int height, PixelFormat pixel_format): + m_pixel_format(pixel_format) + ,m_width(width) + ,m_height(height) +{ + switch (pixel_format) + { + case PixelFormat::ycbcr_422_8: + init_ycbcr422_8(width, height); + break; + case PixelFormat::ycbcr_422_10_le_msb: + init_ycbcr_422_10_le_msb(width, height); + break; + case PixelFormat::ycbcr_444_8: + init_ycbcr_444_8(width, height); + break; + case PixelFormat::ycbcr_422_10_be: + init_ycbcr_422_10_be(width, height); + break; + case PixelFormat::rgb_444_8: + init_rgb_444_8(width, height); + break; + case PixelFormat::bgr_444_8_le_msb: + init_bgr_444_8_le_msb(width, height); + break; + default: break; + } +} + +ColorBar::~ColorBar() +{ + if(m_pattern) + delete[] m_pattern; +} + +uint8_t* ColorBar::get_data() +{ + return m_pattern; +} + +uint64_t ColorBar::get_datasize() +{ + return m_datasize; +} + +void ColorBar::init_ycbcr_422_10_le_msb(int width, int height) +{ + DataV210 color[] = { V210_HD_WHITE75,V210_HD_YELLOW75,V210_HD_CYAN75,V210_HD_GREEN75,V210_HD_MAGENTA75,V210_HD_RED75,V210_HD_BLUE75,V210_HD_BLACK75 }; + m_datasize = width * height * 8 / 3; + m_pattern = new uint8_t[m_datasize]; + if (m_pattern) + { + DataV210* pData_X = (DataV210*)m_pattern; + + for (int pixel = 0; pixel < width * height; pixel += 6) + { + *pData_X = color[(pixel % width) / (width / 8)]; + pData_X++; + } + } +} + +void ColorBar::init_ycbcr_422_10_be(int width, int height) +{ + DataYUV42210BE color[] = { YUV42210BE_WHITE_100, YUV42210BE_YELLOW_100 , YUV42210BE_CYAN_100 , YUV42210BE_GREEN_100 , YUV42210BE_MAGENTA_100, YUV42210BE_RED_100 , YUV42210BE_BLUE_100, YUV42210BE_BLACK_100 }; + m_datasize = width * height * 5 / 2; + m_pattern = new uint8_t[m_datasize]; + if (m_pattern) + { + DataYUV42210BE* pData_X = (DataYUV42210BE*)m_pattern; + for (int pixel = 0; pixel < width * height; pixel += 2) + { + *pData_X = color[(pixel % width) / (width / 8)]; + pData_X++; + } + } +} +void ColorBar::init_ycbcr422_8(int width, int height) +{ + m_datasize = (uint64_t)width * height * 2; + m_pattern = new uint8_t[m_datasize]; + + for (uint64_t x = 0; x < width; x += 2) + { + for (uint64_t y = 0; y < height; y++) + { + if (x < 1 * (width / 8)) + *(uint32_t*)(m_pattern + (x * 2) + (y * width * 2)) = V208_WHITE75; + else if (x < 2 * (width / 8)) + *(uint32_t*)(m_pattern + (x * 2) + (y * width * 2)) = V208_YELLOW75; + else if (x < 3 * (width / 8)) + *(uint32_t*)(m_pattern + (x * 2) + (y * width * 2)) = V208_CYAN75; + else if (x < 4 * (width / 8)) + *(uint32_t*)(m_pattern + (x * 2) + (y * width * 2)) = V208_GREEN75; + else if (x < 5 * (width / 8)) + *(uint32_t*)(m_pattern + (x * 2) + (y * width * 2)) = V208_MAGENTA75; + else if (x < 6 * (width / 8)) + *(uint32_t*)(m_pattern + (x * 2) + (y * width * 2)) = V208_RED75; + else if (x < 7 * (width / 8)) + *(uint32_t*)(m_pattern + (x * 2) + (y * width * 2)) = V208_BLUE75; + else if (x < 8 * (width / 8)) + *(uint32_t*)(m_pattern + (x * 2) + (y * width * 2)) = V208_BLACK75; + } + } +} + +void ColorBar::init_ycbcr_444_8(int width, int height) +{ + m_datasize = (uint64_t)width * height * 3; + m_pattern = new uint8_t[m_datasize]; + + for (uint64_t x = 0; x < width-1; x++) + { + for (uint64_t y = 0; y < height; y++) + { + if (x < 1 * (width / 8)) + *(uint32_t*)(m_pattern + (x * 3) + (y * width * 3)) = Y444_WHITE100_Q; + else if (x < 2 * (width / 8)) + *(uint32_t*)(m_pattern + (x * 3) + (y * width * 3)) = Y444_YELLOW100_Q; + else if (x < 3 * (width / 8)) + *(uint32_t*)(m_pattern + (x * 3) + (y * width * 3)) = Y444_CYAN100_Q; + else if (x < 4 * (width / 8)) + *(uint32_t*)(m_pattern + (x * 3) + (y * width * 3)) = Y444_GREEN100_Q; + else if (x < 5 * (width / 8)) + *(uint32_t*)(m_pattern + (x * 3) + (y * width * 3)) = Y444_MAGENTA100_Q; + else if (x < 6 * (width / 8)) + *(uint32_t*)(m_pattern + (x * 3) + (y * width * 3)) = Y444_RED100_Q; + else if (x < 7 * (width / 8)) + *(uint32_t*)(m_pattern + (x * 3) + (y * width * 3)) = Y444_BLUE100_Q; + else if (x < 8 * (width / 8)) + *(uint32_t*)(m_pattern + (x * 3) + (y * width * 3)) = Y444_BLACK100_Q; + } + } + +} + +void ColorBar::init_rgb_444_8(int width, int height) +{ + m_datasize = (uint64_t)width * height * 3; + m_pattern = new uint8_t[m_datasize]; + + for (uint64_t x = 0; x < width-1; x++) + { + for (uint64_t y = 0; y < height; y++) + { + if (x < 1 * (width / 8)) + *(uint32_t*)(m_pattern + (x * 3) + (y * width * 3)) = R444_WHITE100_Q; + else if (x < 2 * (width / 8)) + *(uint32_t*)(m_pattern + (x * 3) + (y * width * 3)) = R444_YELLOW100_Q; + else if (x < 3 * (width / 8)) + *(uint32_t*)(m_pattern + (x * 3) + (y * width * 3)) = R444_CYAN100_Q; + else if (x < 4 * (width / 8)) + *(uint32_t*)(m_pattern + (x * 3) + (y * width * 3)) = R444_GREEN100_Q; + else if (x < 5 * (width / 8)) + *(uint32_t*)(m_pattern + (x * 3) + (y * width * 3)) = R444_MAGENTA100_Q; + else if (x < 6 * (width / 8)) + *(uint32_t*)(m_pattern + (x * 3) + (y * width * 3)) = R444_RED100_Q; + else if (x < 7 * (width / 8)) + *(uint32_t*)(m_pattern + (x * 3) + (y * width * 3)) = R444_BLUE100_Q; + else if (x < 8 * (width / 8)) + *(uint32_t*)(m_pattern + (x * 3) + (y * width * 3)) = R444_BLACK100_Q; + } + } + +} + +void ColorBar::init_bgr_444_8_le_msb(int width, int height) +{ + + m_datasize = (uint32_t)width * height * 4; + m_pattern = new uint8_t[m_datasize]; + auto m_pattern_32 = (uint32_t*)m_pattern; + + for (uint32_t x = 0; x < width-1; x++) + { + for (uint32_t y = 0; y < height; y++) + { + if (x < 1 * (width / 8)) + *(m_pattern_32 + x + y * width) = BGR444_WHITE100_Q; + else if (x < 2 * (width / 8)) + *(m_pattern_32 + x + y * width) = BGR444_YELLOW100_Q; + else if (x < 3 * (width / 8)) + *(m_pattern_32 + x + y * width) = BGR444_CYAN100_Q; + else if (x < 4 * (width / 8)) + *(m_pattern_32 + x + y * width) = BGR444_GREEN100_Q; + else if (x < 5 * (width / 8)) + *(m_pattern_32 + x + y * width) = BGR444_MAGENTA100_Q; + else if (x < 6 * (width / 8)) + *(m_pattern_32 + x + y * width) = BGR444_RED100_Q; + else if (x < 7 * (width / 8)) + *(m_pattern_32 + x + y * width) = BGR444_BLUE100_Q; + else if (x < 8 * (width / 8)) + *(m_pattern_32 + x + y * width) = BGR444_BLACK100_Q; + } + } +} + + +void ColorBar::draw_moving_line(uint8_t* data, int frame_count) +{ + switch (m_pixel_format) + { + case PixelFormat::ycbcr_422_8: + draw_moving_line_ycbcr_422_8(data, frame_count); + break; + case PixelFormat::ycbcr_422_10_le_msb: + draw_moving_line_ycbcr_422_10_le_msb(data, frame_count); + break; + case PixelFormat::ycbcr_444_8: + draw_moving_line_ycbcr_444_8(data, frame_count); + break; + case PixelFormat::ycbcr_422_10_be: + draw_moving_line_ycbcr_422_10_be(data, frame_count); + break; + case PixelFormat::rgb_444_8: + draw_moving_line_rgb_444_8(data, frame_count); + break; + case PixelFormat::bgr_444_8_le_msb: + draw_moving_line_bgr_444_8_le_msb(data, frame_count); + break; + default: break; + } +} + +void ColorBar::draw_moving_line_ycbcr_422_8(uint8_t* data, int frame_count) +{ + for(uint64_t x = 0; x < m_width; x += 2) + *(uint32_t*)(data + (x * 2) + ((uint64_t)frame_count%m_height) * m_width * 2) = V208_WHITE75; +} + +void ColorBar::draw_moving_line_ycbcr_422_10_le_msb(uint8_t* data, int frame_count) +{ + int line = frame_count % m_height; + + if (line * m_width * 8 % 3 == 0) + { + DataV210* pData_X = (DataV210*)(data + line * m_width * 8 / 3); + for (int x = 0; x < m_width; x += 6) + { + *pData_X = V210_HD_WHITE75; + pData_X++; + } + } + else + { + int pxl = line * m_width; + pxl += (6 - pxl % 6); + + DataV210* pData_X = (DataV210*)(data + pxl*8/3); + + for (int x = 0; x < m_width-6; x += 6) + { + *pData_X = V210_HD_WHITE75; + pData_X++; + } + } + + +} +void ColorBar::draw_moving_line_ycbcr_422_10_be(uint8_t* data, int frame_count) +{ + DataYUV42210BE* pData_X = (DataYUV42210BE*)(data + frame_count % m_height * m_width * 5 / 2); + for (int x = 0; x < m_width; x += 2) + { + *pData_X = YUV42210BE_WHITE_100; + pData_X++; + } + +} + +void ColorBar::draw_moving_line_ycbcr_444_8(uint8_t* data, int frame_count) +{ + for (uint64_t x = 0; x < (m_width-1); x++) + *(uint32_t*)(data + (x * 3) + ((uint64_t)frame_count % m_height) * m_width * 3) = Y444_WHITE100_Q; +} + +void ColorBar::draw_moving_line_rgb_444_8(uint8_t* data, int frame_count) +{ + for (uint64_t x = 0; x < (m_width-1); x++) + *(uint32_t*)(data + (x * 3) + ((uint64_t)frame_count % m_height) * m_width * 3) = R444_WHITE100_Q; +} + +void ColorBar::draw_moving_line_bgr_444_8_le_msb(uint8_t* data, int frame_count) +{ + for (uint64_t x = 0; x < (m_width-1); x++) + *(uint32_t*)(data + (x * 4) + ((uint64_t)frame_count % m_height) * m_width * 4) = BGR444_WHITE100_Q; +} diff --git a/sample/colorbar.hpp b/sample/colorbar.hpp index c8ddd08..a7c2110 100644 --- a/sample/colorbar.hpp +++ b/sample/colorbar.hpp @@ -1,76 +1,79 @@ -/* - * SPDX-FileCopyrightText: Copyright (c) DELTACAST.TV. All rights reserved. - * SPDX-License-Identifier: Apache-2.0 - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -#pragma once - -#include - -namespace Deltacast -{ - class ColorBar - { - public: - - enum class PixelFormat { - ycbcr_422_8, /*< YCbCr 4:2:2 8bit without any padding */ - ycbcr_422_10_le_msb, /*< YCbCr 4:2:2 10bit little endian with msb padding (30/32 bits) */ - ycbcr_422_10_be, /*< YCbCr 4:2:2 10bit big endian without any padding */ - reserved_ycbcr_422_12_le_msb, /*< YCbCr 4:2:2 12bit little endian with msb padding (12/16 bits) */ - reserved_ycbcr_422_12_be, /*< YCbCr 4:2:2 12bit big endian without any padding */ - reserved_ycbcr_422_16_le, /*< YCbCr 4:2:2 16bit little endian without any padding */ - reserved_ycbcr_422_16_be, /*< YCbCr 4:2:2 12bit big endian without any padding */ - ycbcr_444_8, /*< YCbCr 4:4:4 8bit without any padding */ - reserved_ycbcr_444_10_le_msb, /*< YCbCr 4:2:2 10bit little endian with msb padding (30/32 bits) */ - reserved_ycbcr_444_10_be, /*< YCbCr 4:4:4 10bit big endian without any padding */ - reserved_ycbcr_444_12_le_msb, /*< YCbCr 4:4:4 12bit little endian with msb padding (12/16 bits) */ - reserved_ycbcr_444_12_be, /*< YCbCr 4:4:4 12bit big endian without any padding */ - reserved_ycbcr_444_16_le, /*< YCbCr 4:4:4 16bit little endian without any padding */ - reserved_ycbcr_444_16_be, /*< YCbCr 4:4:4 12bit big endian without any padding */ - rgb_444_8, /*< RGB 4:4:4 8bit without any padding */ - reserved_rgb_444_10_le_msb, /*< RGB 4:2:2 10bit little endian with msb padding (30/32 bits) */ - reserved_rgb_444_10_be, /*< RGB 4:4:4 10bit big endian without any padding */ - reserved_rgb_444_12_le_msb, /*< RGB 4:4:4 12bit little endian with msb padding (12/16 bits) */ - reserved_rgb_444_12_be, /*< RGB 4:4:4 12bit big endian without any padding */ - reserved_rgb_444_16_le, /*< RGB 4:4:4 16bit little endian without any padding */ - reserved_rgb_444_16_be, /*< RGB 4:4:4 12bit big endian without any padding */ - nb_pixel_format - }; - - ColorBar(int width, int height, PixelFormat pixel_format); - ~ColorBar(); - - uint8_t* get_data(); - uint64_t get_datasize(); - void draw_moving_line(uint8_t* data, int frame_count); - - private: - void init_ycbcr422_8(int width, int height); - void init_ycbcr_422_10_le_msb(int width, int height); - void init_ycbcr_422_10_be(int width, int height); - void init_ycbcr_444_8(int width, int height); - void init_rgb_444_8(int width, int height); - void draw_moving_line_ycbcr_422_8(uint8_t* data, int frame_count); - void draw_moving_line_ycbcr_422_10_le_msb(uint8_t* data, int frame_count); - void draw_moving_line_ycbcr_444_8(uint8_t* data, int frame_count); - void draw_moving_line_rgb_444_8(uint8_t* data, int frame_count); - void draw_moving_line_ycbcr_422_10_be(uint8_t* data, int frame_count); - - uint8_t* m_pattern{nullptr}; - uint64_t m_datasize{0}; - PixelFormat m_pixel_format{PixelFormat::rgb_444_8}; - int m_width{0}; - int m_height{0}; - }; +/* + * SPDX-FileCopyrightText: Copyright (c) DELTACAST.TV. All rights reserved. + * SPDX-License-Identifier: Apache-2.0 + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#pragma once + +#include + +namespace Deltacast +{ + class ColorBar + { + public: + + enum class PixelFormat { + ycbcr_422_8, /*< YCbCr 4:2:2 8bit without any padding */ + ycbcr_422_10_le_msb, /*< YCbCr 4:2:2 10bit little endian with msb padding (30/32 bits) */ + ycbcr_422_10_be, /*< YCbCr 4:2:2 10bit big endian without any padding */ + reserved_ycbcr_422_12_le_msb, /*< YCbCr 4:2:2 12bit little endian with msb padding (12/16 bits) */ + reserved_ycbcr_422_12_be, /*< YCbCr 4:2:2 12bit big endian without any padding */ + reserved_ycbcr_422_16_le, /*< YCbCr 4:2:2 16bit little endian without any padding */ + reserved_ycbcr_422_16_be, /*< YCbCr 4:2:2 12bit big endian without any padding */ + ycbcr_444_8, /*< YCbCr 4:4:4 8bit without any padding */ + reserved_ycbcr_444_10_le_msb, /*< YCbCr 4:2:2 10bit little endian with msb padding (30/32 bits) */ + reserved_ycbcr_444_10_be, /*< YCbCr 4:4:4 10bit big endian without any padding */ + reserved_ycbcr_444_12_le_msb, /*< YCbCr 4:4:4 12bit little endian with msb padding (12/16 bits) */ + reserved_ycbcr_444_12_be, /*< YCbCr 4:4:4 12bit big endian without any padding */ + reserved_ycbcr_444_16_le, /*< YCbCr 4:4:4 16bit little endian without any padding */ + reserved_ycbcr_444_16_be, /*< YCbCr 4:4:4 12bit big endian without any padding */ + rgb_444_8, /*< RGB 4:4:4 8bit without any padding */ + reserved_rgb_444_10_le_msb, /*< RGB 4:2:2 10bit little endian with msb padding (30/32 bits) */ + reserved_rgb_444_10_be, /*< RGB 4:4:4 10bit big endian without any padding */ + reserved_rgb_444_12_le_msb, /*< RGB 4:4:4 12bit little endian with msb padding (12/16 bits) */ + reserved_rgb_444_12_be, /*< RGB 4:4:4 12bit big endian without any padding */ + reserved_rgb_444_16_le, /*< RGB 4:4:4 16bit little endian without any padding */ + reserved_rgb_444_16_be, /*< RGB 4:4:4 12bit big endian without any padding */ + bgr_444_8_le_msb, + nb_pixel_format + }; + + ColorBar(int width, int height, PixelFormat pixel_format); + ~ColorBar(); + + uint8_t* get_data(); + uint64_t get_datasize(); + void draw_moving_line(uint8_t* data, int frame_count); + + private: + void init_ycbcr422_8(int width, int height); + void init_ycbcr_422_10_le_msb(int width, int height); + void init_ycbcr_422_10_be(int width, int height); + void init_ycbcr_444_8(int width, int height); + void init_rgb_444_8(int width, int height); + void init_bgr_444_8_le_msb(int width, int height); + void draw_moving_line_ycbcr_422_8(uint8_t* data, int frame_count); + void draw_moving_line_ycbcr_422_10_le_msb(uint8_t* data, int frame_count); + void draw_moving_line_ycbcr_444_8(uint8_t* data, int frame_count); + void draw_moving_line_rgb_444_8(uint8_t* data, int frame_count); + void draw_moving_line_ycbcr_422_10_be(uint8_t* data, int frame_count); + void draw_moving_line_bgr_444_8_le_msb(uint8_t* data, int frame_count); + + uint8_t* m_pattern{nullptr}; + uint64_t m_datasize{0}; + PixelFormat m_pixel_format{PixelFormat::rgb_444_8}; + int m_width{0}; + int m_height{0}; + }; } \ No newline at end of file diff --git a/sample/main.cpp b/sample/main.cpp index fc2dcf2..819baed 100644 --- a/sample/main.cpp +++ b/sample/main.cpp @@ -1,118 +1,120 @@ -/* - * SPDX-FileCopyrightText: Copyright (c) DELTACAST.TV. All rights reserved. - * SPDX-License-Identifier: Apache-2.0 - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -#include -#include "colorbar.hpp" -#include -#include - -#if defined(WIN32) || defined(_WIN32) -#include -#include -#else -#include -#include -#include "../dep/keyboard.h" -#endif - -bool stop = false; - -#if defined(WIN32) || defined(_WIN32) -#define SLEEP(frame_rate_in_ms) Sleep(frame_rate_in_ms); -#define init_keyboard() -#define close_keyboard() -#else -#define SLEEP(frame_rate_in_ms) usleep(frame_rate_in_ms * 1000); -#endif - -//This function is called inside a new thread that will be used to generate the pattern and copy it to the video buffer -void pattern_thread(Deltacast::VideoViewer& viewer,int frame_rate_in_ms, int width, int height, Deltacast::ColorBar::PixelFormat pixel_format) -{ - int frame_count = 0; - uint8_t* data = nullptr; - uint64_t size = 0; - Deltacast::ColorBar color_bar(width, height, pixel_format); - - while (!stop) - { - if (viewer.lock_data(&data, &size)) { - if (size == color_bar.get_datasize() && color_bar.get_data()) - { - if (data) - { - memcpy(data, color_bar.get_data(), size); - color_bar.draw_moving_line(data, frame_count); - } - } - - viewer.unlock_data(); - } - else - break; - - SLEEP(frame_rate_in_ms); - frame_count++; - } -} - -//This function is called inside a new thread that will be used to render the video -void render_video(Deltacast::VideoViewer& viewer,int window_width, int window_height, const char* window_title, int texture_width, int texture_height, Deltacast::VideoViewer::InputFormat input_format, int frame_rate_in_ms) -{ - if (viewer.init(window_width, window_height, window_title, texture_width, texture_height, input_format)) - { - viewer.render_loop(frame_rate_in_ms); - viewer.release(); - } - else - std::cout << "VideoViewer initialization failed" << std::endl; -} - -int main(int argc, char** argv) -{ - Deltacast::VideoViewer viewer; - init_keyboard(); - - int texture_width = 1920; - int texture_height = 1080; - - //Starting VideoViewer rendering inside a new thread - std::thread viewerthread(render_video, std::ref(viewer), 800, 600, "My window", texture_width, texture_height, Deltacast::VideoViewer::InputFormat::rgb_444_8, 10); - - //Starting Pattern Generator inside a new thread - std::thread pattern_generator(pattern_thread, std::ref(viewer), 10, texture_width, texture_height, Deltacast::ColorBar::PixelFormat::rgb_444_8); - - std::cout << "Press any key to stop or close Opengl window..." << std::endl; - while (!viewer.window_request_close()) - { - if (_kbhit()) - { - _getch(); - break; - } - SLEEP(100); - } - - //Stopping Pattern Generator - stop = true; - pattern_generator.join(); - - //Stopping VideoViewer - viewer.stop(); - viewerthread.join(); - - close_keyboard(); - - return 0; +/* + * SPDX-FileCopyrightText: Copyright (c) DELTACAST.TV. All rights reserved. + * SPDX-License-Identifier: Apache-2.0 + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include +#include "colorbar.hpp" +#include +#include + +#if defined(WIN32) || defined(_WIN32) +#include +#include +#else +#include +#include +#include "../dep/keyboard.h" +#endif + +bool stop = false; + +#if defined(WIN32) || defined(_WIN32) +#define SLEEP(frame_rate_in_ms) Sleep(frame_rate_in_ms); +#define init_keyboard() +#define close_keyboard() +#else +#define SLEEP(frame_rate_in_ms) usleep(frame_rate_in_ms * 1000); +#endif + +//This function is called inside a new thread that will be used to generate the pattern and copy it to the video buffer +void pattern_thread(Deltacast::VideoViewer& viewer,int frame_rate_in_ms, int width, int height, Deltacast::ColorBar::PixelFormat pixel_format) +{ + int frame_count = 0; + uint8_t* data = nullptr; + uint64_t size = 0; + Deltacast::ColorBar color_bar(width, height, pixel_format); + + while (!stop) + { + if (viewer.lock_data(&data, &size)) { + if (size == color_bar.get_datasize() && color_bar.get_data()) + { + if (data) + { + memcpy(data, color_bar.get_data(), size); + color_bar.draw_moving_line(data, frame_count); + } + } + else + std::cout << "memcpy error: The color bar data size is different from the video buffer size or is null" << std::endl; + + viewer.unlock_data(); + } + else + break; + + SLEEP(frame_rate_in_ms); + frame_count++; + } +} + +//This function is called inside a new thread that will be used to render the video +void render_video(Deltacast::VideoViewer& viewer,int window_width, int window_height, const char* window_title, int texture_width, int texture_height, Deltacast::VideoViewer::InputFormat input_format, int frame_rate_in_ms) +{ + if (viewer.init(window_width, window_height, window_title, texture_width, texture_height, input_format)) + { + viewer.render_loop(frame_rate_in_ms); + viewer.release(); + } + else + std::cout << "VideoViewer initialization failed" << std::endl; +} + +int main(int argc, char** argv) +{ + Deltacast::VideoViewer viewer; + init_keyboard(); + + int texture_width = 1920; + int texture_height = 1080; + + //Starting VideoViewer rendering inside a new thread + std::thread viewerthread(render_video, std::ref(viewer), 800, 600, "My window", texture_width, texture_height, Deltacast::VideoViewer::InputFormat::rgb_444_8, 10); + + //Starting Pattern Generator inside a new thread + std::thread pattern_generator(pattern_thread, std::ref(viewer), 10, texture_width, texture_height, Deltacast::ColorBar::PixelFormat::rgb_444_8); + + std::cout << "Press any key to stop or close Opengl window..." << std::endl; + while (!viewer.window_request_close()) + { + if (_kbhit()) + { + _getch(); + break; + } + SLEEP(100); + } + + //Stopping Pattern Generator + stop = true; + pattern_generator.join(); + + //Stopping VideoViewer + viewer.stop(); + viewerthread.join(); + + close_keyboard(); + + return 0; } \ No newline at end of file diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt index f33bc97..826f087 100644 --- a/src/CMakeLists.txt +++ b/src/CMakeLists.txt @@ -36,6 +36,7 @@ target_sources(video-viewer PRIVATE ${PROJECT_SOURCE_DIR}/src/ycbcr444_8_to_rgb444.shader ${PROJECT_SOURCE_DIR}/src/rgb444_8_to_rgb4444.shader ${PROJECT_SOURCE_DIR}/src/ycbcr422_10_be_to_rgb444.shader + ${PROJECT_SOURCE_DIR}/src/bgr4444_8_to_rgb4444.shader ${gl3w_BINARY_DIR}/src/gl3w.c ) diff --git a/src/bgr4444_8_to_rgb4444.shader b/src/bgr4444_8_to_rgb4444.shader new file mode 100644 index 0000000..4122e8b --- /dev/null +++ b/src/bgr4444_8_to_rgb4444.shader @@ -0,0 +1,16 @@ +constexpr char const * compute_shader_bgr_444_8_le_msb = R"( +#version 430 + +layout(local_size_x = 8, local_size_y = 8) in; + +layout(rgba8, binding = 0) uniform image2D img_output; +layout(rgba8, binding = 1) uniform image2D img_input; + +void main() +{ + ivec2 pixelCoords = ivec2(gl_GlobalInvocationID); + vec4 bgra = imageLoad(img_input, ivec2(pixelCoords.x,pixelCoords.y)); + vec4 rgba = vec4(bgra.z, bgra.y, bgra.x, 1.0); + imageStore(img_output, pixelCoords, rgba); +}; +)"; diff --git a/src/bgr444_8_to_rgb4444.shader b/src/bgr444_8_to_rgb4444.shader index 1d99214..39c9c0d 100644 --- a/src/bgr444_8_to_rgb4444.shader +++ b/src/bgr444_8_to_rgb4444.shader @@ -1,50 +1,50 @@ -constexpr char const * compute_shader_bgr_444_8 = +constexpr char const * compute_shader_bgr_444_8 = R"( { -"#version 430\n" -"\n" -"layout(local_size_x = 8, local_size_y = 8) in;\n" -"\n" -"layout(rgba8, binding = 0) uniform image2D img_output;\n" -"layout(rgba8, binding = 1) uniform image2D img_input;\n" -"\n" -"void main() {\n" -" int width = imageSize(img_output).x;\n" -" ivec2 coords = ivec2(gl_GlobalInvocationID);\n" -" float PxlIdx = coords.x + coords.y * width;\n" -" vec4 bgr;\n" -" vec4 rgba;\n" -" rgba.w = 1.0;\n" -" if (mod(PxlIdx, 4.0) < 1.0)\n" -" {\n" -" bgr = imageLoad(img_input, ivec2(coords.x*3.0/4.0 , coords.y));\n" -" rgba.z = bgr.x;\n" -" rgba.y = bgr.y;\n" -" rgba.x = bgr.z;\n" -" }\n" -" else if (mod(PxlIdx, 4.0) < 2.0)\n" -" {\n" -" bgr = imageLoad(img_input, ivec2(int(coords.x*3.0/4.0) , coords.y));\n" -" rgba.z = bgr.w;\n" -" bgr = imageLoad(img_input, ivec2(int(coords.x*3.0/4.0) + 1 , coords.y));\n" -" rgba.y = bgr.x;\n" -" rgba.x = bgr.y;\n" -" }\n" -" else if (mod(PxlIdx, 4.0) < 3.0)\n" -" {\n" -" bgr = imageLoad(img_input, ivec2(int(coords.x*3.0/4.0) , coords.y));\n" -" rgba.z = bgr.z;\n" -" rgba.y = bgr.w;\n" -" bgr = imageLoad(img_input, ivec2(int(coords.x*3.0/4.0) + 1 , coords.y));\n" -" rgba.x = bgr.x;\n" -" }\n" -" else if (mod(PxlIdx, 4.0) < 4.0)\n" -" {\n" -" bgr = imageLoad(img_input, ivec2(int(coords.x*3.0/4.0) , coords.y));\n" -" rgba.z = bgr.y;\n" -" rgba.y = bgr.z;\n" -" rgba.x = bgr.w;\n" -" }\n" -"\n" -" imageStore(img_output, coords, rgba);\n" -"}\n" -}; +#version 430 + +layout(local_size_x = 8, local_size_y = 8) in; + +layout(rgba8, binding = 0) uniform image2D img_output; +layout(rgba8, binding = 1) uniform image2D img_input; + +void main() { + int width = imageSize(img_output).x; + ivec2 coords = ivec2(gl_GlobalInvocationID); + float PxlIdx = coords.x + coords.y * width; + vec4 bgr; + vec4 rgba; + rgba.w = 1.0; + if (mod(PxlIdx, 4.0) < 1.0) + { + bgr = imageLoad(img_input, ivec2(coords.x*3.0/4.0 , coords.y)); + rgba.z = bgr.x; + rgba.y = bgr.y; + rgba.x = bgr.z; + } + else if (mod(PxlIdx, 4.0) < 2.0) + { + bgr = imageLoad(img_input, ivec2(int(coords.x*3.0/4.0) , coords.y)); + rgba.z = bgr.w; + bgr = imageLoad(img_input, ivec2(int(coords.x*3.0/4.0) + 1 , coords.y)); + rgba.y = bgr.x; + rgba.x = bgr.y; + } + else if (mod(PxlIdx, 4.0) < 3.0) + { + bgr = imageLoad(img_input, ivec2(int(coords.x*3.0/4.0) , coords.y)); + rgba.z = bgr.z; + rgba.y = bgr.w; + bgr = imageLoad(img_input, ivec2(int(coords.x*3.0/4.0) + 1 , coords.y)); + rgba.x = bgr.x; + } + else if (mod(PxlIdx, 4.0) < 4.0) + { + bgr = imageLoad(img_input, ivec2(int(coords.x*3.0/4.0) , coords.y)); + rgba.z = bgr.y; + rgba.y = bgr.z; + rgba.x = bgr.w; + } + + imageStore(img_output, coords, rgba); +} +)"; diff --git a/src/rgb444_8_to_rgb4444.shader b/src/rgb444_8_to_rgb4444.shader index 2934d5b..d38137a 100644 --- a/src/rgb444_8_to_rgb4444.shader +++ b/src/rgb444_8_to_rgb4444.shader @@ -1,50 +1,50 @@ -constexpr char const * compute_shader_rgb_444_8 = -{ -"#version 430\n" -"\n" -"layout(local_size_x = 8, local_size_y = 8) in;\n" -"\n" -"layout(rgba8, binding = 0) uniform image2D img_output;\n" -"layout(rgba8, binding = 1) uniform image2D img_input;\n" -"\n" -"void main() {\n" -" int width = imageSize(img_output).x;\n" -" ivec2 coords = ivec2(gl_GlobalInvocationID);\n" -" float PxlIdx = coords.x + coords.y * width;\n" -" vec4 rgb;\n" -" vec4 rgba;\n" -" rgba.w = 1.0;\n" -" if (mod(PxlIdx, 4.0) < 1.0)\n" -" {\n" -" rgb = imageLoad(img_input, ivec2(coords.x*3.0/4.0 , coords.y));\n" -" rgba.x = rgb.x;\n" -" rgba.y = rgb.y;\n" -" rgba.z = rgb.z;\n" -" }\n" -" else if (mod(PxlIdx, 4.0) < 2.0)\n" -" {\n" -" rgb = imageLoad(img_input, ivec2(int(coords.x*3.0/4.0) , coords.y));\n" -" rgba.x = rgb.w;\n" -" rgb = imageLoad(img_input, ivec2(int(coords.x*3.0/4.0) + 1 , coords.y));\n" -" rgba.y = rgb.x;\n" -" rgba.z = rgb.y;\n" -" }\n" -" else if (mod(PxlIdx, 4.0) < 3.0)\n" -" {\n" -" rgb = imageLoad(img_input, ivec2(int(coords.x*3.0/4.0) , coords.y));\n" -" rgba.x = rgb.z;\n" -" rgba.y = rgb.w;\n" -" rgb = imageLoad(img_input, ivec2(int(coords.x*3.0/4.0) + 1 , coords.y));\n" -" rgba.z = rgb.x;\n" -" }\n" -" else if (mod(PxlIdx, 4.0) < 4.0)\n" -" {\n" -" rgb = imageLoad(img_input, ivec2(int(coords.x*3.0/4.0) , coords.y));\n" -" rgba.x = rgb.y;\n" -" rgba.y = rgb.z;\n" -" rgba.z = rgb.w;\n" -" }\n" -"\n" -" imageStore(img_output, coords, rgba);\n" -"}\n" -}; \ No newline at end of file +constexpr char const * compute_shader_rgb_444_8 = R"( +{ +#version 430 + +layout(local_size_x = 8, local_size_y = 8) in; + +layout(rgba8, binding = 0) uniform image2D img_output; +layout(rgba8, binding = 1) uniform image2D img_input; + +void main() { + int width = imageSize(img_output).x; + ivec2 coords = ivec2(gl_GlobalInvocationID); + float PxlIdx = coords.x + coords.y * width; + vec4 rgb; + vec4 rgba; + rgba.w = 1.0; + if (mod(PxlIdx, 4.0) < 1.0) + { + rgb = imageLoad(img_input, ivec2(coords.x*3.0/4.0 , coords.y)); + rgba.x = rgb.x; + rgba.y = rgb.y; + rgba.z = rgb.z; + } + else if (mod(PxlIdx, 4.0) < 2.0) + { + rgb = imageLoad(img_input, ivec2(int(coords.x*3.0/4.0) , coords.y)); + rgba.x = rgb.w; + rgb = imageLoad(img_input, ivec2(int(coords.x*3.0/4.0) + 1 , coords.y)); + rgba.y = rgb.x; + rgba.z = rgb.y; + } + else if (mod(PxlIdx, 4.0) < 3.0) + { + rgb = imageLoad(img_input, ivec2(int(coords.x*3.0/4.0) , coords.y)); + rgba.x = rgb.z; + rgba.y = rgb.w; + rgb = imageLoad(img_input, ivec2(int(coords.x*3.0/4.0) + 1 , coords.y)); + rgba.z = rgb.x; + } + else if (mod(PxlIdx, 4.0) < 4.0) + { + rgb = imageLoad(img_input, ivec2(int(coords.x*3.0/4.0) , coords.y)); + rgba.x = rgb.y; + rgba.y = rgb.z; + rgba.z = rgb.w; + } + + imageStore(img_output, coords, rgba); +} +)"; \ No newline at end of file diff --git a/src/vertex.shader b/src/vertex.shader index 9d0b7ea..5887f10 100644 --- a/src/vertex.shader +++ b/src/vertex.shader @@ -1,17 +1,17 @@ -constexpr char const * vertex_shader_src = -{ -"#version 430\n" -"\n" -"in vec3 vertex;\n" -"layout(location = 0) in vec2 position;\n" -"layout(location = 1) in vec2 texCoord;\n" -"\n" -"out vec4 inColor;\n" -"out vec2 TexCoord;\n" -"\n" -"void main() {\n" -" gl_Position = vec4(position, .5f, 1.0f);\n" -" inColor = gl_Position;\n" -" TexCoord = texCoord;\n" -"}\n" -}; \ No newline at end of file +constexpr char const * vertex_shader_src = R"( +{ +#version 430 + +in vec3 vertex; +layout(location = 0) in vec2 position; +layout(location = 1) in vec2 texCoord; + +out vec4 inColor; +out vec2 TexCoord; + +void main() { + gl_Position = vec4(position, .5f, 1.0f); + inColor = gl_Position; + TexCoord = texCoord; +} +)"; \ No newline at end of file diff --git a/src/videoviewer_internal.cpp b/src/videoviewer_internal.cpp index 4379e70..081c677 100644 --- a/src/videoviewer_internal.cpp +++ b/src/videoviewer_internal.cpp @@ -20,6 +20,7 @@ #include "ycbcr444_8_to_rgb444.shader" #include "rgb444_8_to_rgb4444.shader" #include "bgr444_8_to_rgb4444.shader" +#include "bgr4444_8_to_rgb4444.shader" #include "vertex.shader" #include "fragment.shader" #include @@ -260,6 +261,12 @@ bool VideoViewer_Internal::init(int texture_width, int texture_height, Deltacast m_input_texture_height = m_texture_height; compute_shader_name = compute_shader_422_10_be; break; + case Deltacast::VideoViewer::InputFormat::bgr_444_8_le_msb: + input_buffer_size = (uint64_t)m_texture_width * (uint64_t)m_texture_height * 4; + m_input_texture_width = m_texture_width; + m_input_texture_height = m_texture_height; + compute_shader_name = compute_shader_bgr_444_8_le_msb; + break; default: return false; } diff --git a/src/ycbcr422_10_be_to_rgb444.shader b/src/ycbcr422_10_be_to_rgb444.shader index d37b221..dd3649a 100644 --- a/src/ycbcr422_10_be_to_rgb444.shader +++ b/src/ycbcr422_10_be_to_rgb444.shader @@ -1,97 +1,97 @@ -constexpr char const *compute_shader_422_10_be = -{ -"#version 430\n" -"\n" -"layout(local_size_x = 8, local_size_y = 8) in;\n" -"\n" -"layout(rgba8, binding = 0) uniform image2D img_output;\n" -"layout(rgba8, binding = 1) uniform image2D img_input;\n" -"\n" -"vec4 yuv2rgba(vec4 yuvk)\n" -"{\n" -" vec4 rgba;\n" -" bool bt_709 = true; //TODO: pass this information from the code\n" -"\n" -" rgba.x = 1.164 * (yuvk.x - 16.0 / 255.0) + ((float(bt_709) * 1.793) + (float(!bt_709)) * (1.596)) * (yuvk.z - 128.0 / 255.0);\n" -" rgba.y = 1.164 * (yuvk.x - 16.0 / 255.0) - ((float(bt_709) * 0.534) + (float(!bt_709)) * (0.813)) * (yuvk.z - 128.0 / 255.0) - 0.213 * (yuvk.y - 128.0 / 255.0);\n" -" rgba.z = 1.164 * (yuvk.x - 16.0 / 255.0) + ((float(bt_709) * 2.115) + (float(!bt_709)) * (2.018)) * (yuvk.y - 128.0 / 255.0);\n" -" rgba.w = 1.0;\n" -" return rgba;\n" -"}\n" -"\n" -"void main() {\n" -" int width = imageSize(img_output).x;\n" -" ivec2 coords = ivec2(gl_GlobalInvocationID);\n" -" vec4 uyvy;\n" -" vec4 uyvy2;\n" -" float PxlIdx = coords.x + coords.y * width;\n" -" vec4 yuvk;\n" -" yuvk.w = 1.0;\n" -"\n" -" if (mod(PxlIdx, 8.0) < 1.0)\n" -" {\n" -" uyvy = imageLoad(img_input, ivec2(int(coords.x * 5.0 / 8.0), coords.y));\n" -" yuvk.x = ((mod(uyvy.y * 255.0,64) * 16) + (int(uyvy.z * 255.0 / 16.0))) / 1023.0;\n" -" yuvk.y = ((uyvy.x * 255.0 * 4.0) + (int(uyvy.y * 255.0 / 64.0))) / 1023.0;\n" -" yuvk.z = ((mod(uyvy.z * 255.0,16.0) * 64.0) + (int(uyvy.w * 255.0 / 4.0))) / 1023.0;\n" -" }\n" -" else if (mod(PxlIdx, 8.0) < 2.0)\n" -" {\n" -" uyvy = imageLoad(img_input, ivec2(int(coords.x * 5.0 / 8.0), coords.y));\n" -" yuvk.y = ((uyvy.x * 255.0 * 4.0) + (uyvy.y * 255.0 / 64.0)) / 1023.0;\n" -" yuvk.z = ((mod(uyvy.z * 255.0,16.0) * 64.0) + (uyvy.w * 255.0 / 4.0)) / 1023.0;\n" -" uyvy2 = imageLoad(img_input, ivec2(int(coords.x * 5.0 / 8.0) + 1, coords.y));\n" -" yuvk.x = (uyvy2.x * 255.0 + (mod(uyvy.w * 255.0,4.0) * 256.0)) / 1023.0;\n" -" }\n" -" else if (mod(PxlIdx, 8.0) < 3.0)\n" -" {\n" -" uyvy = imageLoad(img_input, ivec2(int(coords.x * 5.0 / 8.0), coords.y));\n" -" yuvk.x = ((mod(uyvy.z * 255.0, 64.0) * 16.0) + (uyvy.w * 255.0 / 16.0)) / 1023.0;\n" -" yuvk.y = ((uyvy.y * 255.0 * 4.0) + (uyvy.z * 255.0 / 64.0)) / 1023.0;\n" -" uyvy2 = imageLoad(img_input, ivec2(int(coords.x * 5.0 / 8.0) + 1, coords.y));\n" -" yuvk.z = ((mod(uyvy.w * 255.0,16.0) * 64.0) + (uyvy2.x * 255.0 / 4.0)) / 1023.0;\n" -" }\n" -" else if (mod(PxlIdx, 8.0) < 4.0)\n" -" {\n" -" uyvy = imageLoad(img_input, ivec2(int(coords.x * 5.0 / 8.0) + 1, coords.y));\n" -" yuvk.x = (uyvy.y * 255.0 + (mod(uyvy.x * 255.0,4.0) * 256.0)) / 1023.0;\n" -" uyvy2 = imageLoad(img_input, ivec2(int(coords.x * 5.0 / 8.0), coords.y));\n" -" yuvk.y = ((uyvy2.y * 255.0 * 4.0) + (uyvy2.z * 255.0 / 64.0)) / 1023.0;\n" -" yuvk.z = ((mod(uyvy2.w * 255.0,16.0) * 64.0) + (uyvy.x * 255.0 / 4.0)) / 1023.0;\n" -" }\n" -" else if (mod(PxlIdx, 8.0) < 5.0)\n" -" {\n" -" uyvy = imageLoad(img_input, ivec2(int(coords.x * 5.0 / 8.0), coords.y));\n" -" uyvy2 = imageLoad(img_input, ivec2(int(coords.x * 5.0 / 8.0) + 1 , coords.y));\n" -" yuvk.x = ((mod(uyvy.w * 255.0, 64.0) * 16.0) + (uyvy2.x * 255.0 / 16.0)) / 1023.0;\n" -" yuvk.y = ((uyvy.z * 255.0 * 4.0) + (uyvy.w * 255.0 / 64.0)) / 1023.0;\n" -" yuvk.z = ((mod(uyvy2.x * 255.0,16.0) * 64.0) + (uyvy2.y * 255.0 / 4.0)) / 1023.0;\n" -" }\n" -" else if (mod(PxlIdx, 8.0) < 6.0)\n" -" {\n" -" uyvy = imageLoad(img_input, ivec2(int(coords.x * 5.0 / 8.0), coords.y));\n" -" yuvk.x = (uyvy.z * 255.0 + (mod(uyvy.y * 255.0,4.0) * 256.0)) / 1023.0;\n" -" uyvy2 = imageLoad(img_input, ivec2(int(coords.x * 5.0 / 8.0) - 1 , coords.y));\n" -" yuvk.y = ((uyvy2.z * 255.0 * 4.0) + (uyvy2.w * 255.0 / 64.0)) / 1023.0;\n" -" yuvk.z = ((mod(uyvy.x * 255.0,16.0) * 64.0) + (uyvy.y * 255.0 / 4.0)) / 1023.0;\n" -" }\n" -" else if (mod(PxlIdx, 8.0) < 7.0)\n" -" {\n" -" uyvy = imageLoad(img_input, ivec2(int(coords.x * 5.0 / 8.0), coords.y));\n" -" uyvy2 = imageLoad(img_input, ivec2(int(coords.x * 5.0 / 8.0) + 1 , coords.y));\n" -" yuvk.x = ((mod(uyvy2.x * 255.0, 64.0) * 16.0) + (uyvy2.y * 255.0 / 16.0)) / 1023.0;\n" -" yuvk.y = ((uyvy.w * 255.0 * 4.0) + (uyvy2.x * 255.0 / 64.0)) / 1023.0;\n" -" yuvk.z = ((mod(uyvy2.y * 255.0,16.0) * 64.0) + (uyvy2.z * 255.0 / 4.0)) / 1023.0;\n" -" }\n" -" else\n" -" {\n" -" uyvy = imageLoad(img_input, ivec2(int(coords.x * 5.0 / 8.0), coords.y));\n" -" uyvy2 = imageLoad(img_input, ivec2(int(coords.x * 5.0 / 8.0) - 1, coords.y));\n" -" yuvk.x = (uyvy.w * 255.0 + (mod(uyvy.z * 255.0,4.0) * 256.0)) / 1023.0;\n" -" yuvk.y = ((uyvy2.w * 255.0 * 4.0) + (uyvy.x * 255.0 / 64.0)) / 1023.0;\n" -" yuvk.z = ((mod(uyvy.y * 255.0,16.0) * 64.0) + (uyvy.z * 255.0 / 4.0)) / 1023.0;\n" -" }\n" -"\n" -" imageStore(img_output, coords, yuv2rgba(yuvk));\n" -"}\n" -}; \ No newline at end of file +constexpr char const *compute_shader_422_10_be = R"( +{ +#version 430 + +layout(local_size_x = 8, local_size_y = 8) in; + +layout(rgba8, binding = 0) uniform image2D img_output; +layout(rgba8, binding = 1) uniform image2D img_input; + +vec4 yuv2rgba(vec4 yuvk) +{ + vec4 rgba; + bool bt_709 = true; //TODO: pass this information from the code + + rgba.x = 1.164 * (yuvk.x - 16.0 / 255.0) + ((float(bt_709) * 1.793) + (float(!bt_709)) * (1.596)) * (yuvk.z - 128.0 / 255.0); + rgba.y = 1.164 * (yuvk.x - 16.0 / 255.0) - ((float(bt_709) * 0.534) + (float(!bt_709)) * (0.813)) * (yuvk.z - 128.0 / 255.0) - 0.213 * (yuvk.y - 128.0 / 255.0); + rgba.z = 1.164 * (yuvk.x - 16.0 / 255.0) + ((float(bt_709) * 2.115) + (float(!bt_709)) * (2.018)) * (yuvk.y - 128.0 / 255.0); + rgba.w = 1.0; + return rgba; +} + +void main() { + int width = imageSize(img_output).x; + ivec2 coords = ivec2(gl_GlobalInvocationID); + vec4 uyvy; + vec4 uyvy2; + float PxlIdx = coords.x + coords.y * width; + vec4 yuvk; + yuvk.w = 1.0; + + if (mod(PxlIdx, 8.0) < 1.0) + { + uyvy = imageLoad(img_input, ivec2(int(coords.x * 5.0 / 8.0), coords.y)); + yuvk.x = ((mod(uyvy.y * 255.0,64) * 16) + (int(uyvy.z * 255.0 / 16.0))) / 1023.0; + yuvk.y = ((uyvy.x * 255.0 * 4.0) + (int(uyvy.y * 255.0 / 64.0))) / 1023.0; + yuvk.z = ((mod(uyvy.z * 255.0,16.0) * 64.0) + (int(uyvy.w * 255.0 / 4.0))) / 1023.0; + } + else if (mod(PxlIdx, 8.0) < 2.0) + { + uyvy = imageLoad(img_input, ivec2(int(coords.x * 5.0 / 8.0), coords.y)); + yuvk.y = ((uyvy.x * 255.0 * 4.0) + (uyvy.y * 255.0 / 64.0)) / 1023.0; + yuvk.z = ((mod(uyvy.z * 255.0,16.0) * 64.0) + (uyvy.w * 255.0 / 4.0)) / 1023.0; + uyvy2 = imageLoad(img_input, ivec2(int(coords.x * 5.0 / 8.0) + 1, coords.y)); + yuvk.x = (uyvy2.x * 255.0 + (mod(uyvy.w * 255.0,4.0) * 256.0)) / 1023.0; + } + else if (mod(PxlIdx, 8.0) < 3.0) + { + uyvy = imageLoad(img_input, ivec2(int(coords.x * 5.0 / 8.0), coords.y)); + yuvk.x = ((mod(uyvy.z * 255.0, 64.0) * 16.0) + (uyvy.w * 255.0 / 16.0)) / 1023.0; + yuvk.y = ((uyvy.y * 255.0 * 4.0) + (uyvy.z * 255.0 / 64.0)) / 1023.0; + uyvy2 = imageLoad(img_input, ivec2(int(coords.x * 5.0 / 8.0) + 1, coords.y)); + yuvk.z = ((mod(uyvy.w * 255.0,16.0) * 64.0) + (uyvy2.x * 255.0 / 4.0)) / 1023.0; + } + else if (mod(PxlIdx, 8.0) < 4.0) + { + uyvy = imageLoad(img_input, ivec2(int(coords.x * 5.0 / 8.0) + 1, coords.y)); + yuvk.x = (uyvy.y * 255.0 + (mod(uyvy.x * 255.0,4.0) * 256.0)) / 1023.0; + uyvy2 = imageLoad(img_input, ivec2(int(coords.x * 5.0 / 8.0), coords.y)); + yuvk.y = ((uyvy2.y * 255.0 * 4.0) + (uyvy2.z * 255.0 / 64.0)) / 1023.0; + yuvk.z = ((mod(uyvy2.w * 255.0,16.0) * 64.0) + (uyvy.x * 255.0 / 4.0)) / 1023.0; + } + else if (mod(PxlIdx, 8.0) < 5.0) + { + uyvy = imageLoad(img_input, ivec2(int(coords.x * 5.0 / 8.0), coords.y)); + uyvy2 = imageLoad(img_input, ivec2(int(coords.x * 5.0 / 8.0) + 1 , coords.y)); + yuvk.x = ((mod(uyvy.w * 255.0, 64.0) * 16.0) + (uyvy2.x * 255.0 / 16.0)) / 1023.0; + yuvk.y = ((uyvy.z * 255.0 * 4.0) + (uyvy.w * 255.0 / 64.0)) / 1023.0; + yuvk.z = ((mod(uyvy2.x * 255.0,16.0) * 64.0) + (uyvy2.y * 255.0 / 4.0)) / 1023.0; + } + else if (mod(PxlIdx, 8.0) < 6.0) + { + uyvy = imageLoad(img_input, ivec2(int(coords.x * 5.0 / 8.0), coords.y)); + yuvk.x = (uyvy.z * 255.0 + (mod(uyvy.y * 255.0,4.0) * 256.0)) / 1023.0; + uyvy2 = imageLoad(img_input, ivec2(int(coords.x * 5.0 / 8.0) - 1 , coords.y)); + yuvk.y = ((uyvy2.z * 255.0 * 4.0) + (uyvy2.w * 255.0 / 64.0)) / 1023.0; + yuvk.z = ((mod(uyvy.x * 255.0,16.0) * 64.0) + (uyvy.y * 255.0 / 4.0)) / 1023.0; + } + else if (mod(PxlIdx, 8.0) < 7.0) + { + uyvy = imageLoad(img_input, ivec2(int(coords.x * 5.0 / 8.0), coords.y)); + uyvy2 = imageLoad(img_input, ivec2(int(coords.x * 5.0 / 8.0) + 1 , coords.y)); + yuvk.x = ((mod(uyvy2.x * 255.0, 64.0) * 16.0) + (uyvy2.y * 255.0 / 16.0)) / 1023.0; + yuvk.y = ((uyvy.w * 255.0 * 4.0) + (uyvy2.x * 255.0 / 64.0)) / 1023.0; + yuvk.z = ((mod(uyvy2.y * 255.0,16.0) * 64.0) + (uyvy2.z * 255.0 / 4.0)) / 1023.0; + } + else + { + uyvy = imageLoad(img_input, ivec2(int(coords.x * 5.0 / 8.0), coords.y)); + uyvy2 = imageLoad(img_input, ivec2(int(coords.x * 5.0 / 8.0) - 1, coords.y)); + yuvk.x = (uyvy.w * 255.0 + (mod(uyvy.z * 255.0,4.0) * 256.0)) / 1023.0; + yuvk.y = ((uyvy2.w * 255.0 * 4.0) + (uyvy.x * 255.0 / 64.0)) / 1023.0; + yuvk.z = ((mod(uyvy.y * 255.0,16.0) * 64.0) + (uyvy.z * 255.0 / 4.0)) / 1023.0; + } + + imageStore(img_output, coords, yuv2rgba(yuvk)); +} +)"; \ No newline at end of file diff --git a/src/ycbcr422_10_le_msb_to_rgb444.shader b/src/ycbcr422_10_le_msb_to_rgb444.shader index 419617e..d1c10df 100644 --- a/src/ycbcr422_10_le_msb_to_rgb444.shader +++ b/src/ycbcr422_10_le_msb_to_rgb444.shader @@ -1,80 +1,80 @@ -constexpr char const *compute_shader_422_10_le_msb = -{ -"#version 430\n" -"\n" -"layout(local_size_x = 8, local_size_y = 8) in;\n" -"\n" -"layout(rgba8, binding = 0) uniform image2D img_output;\n" -"layout(rgba8, binding = 1) uniform image2D img_input;\n" -"\n" -"vec4 yuv2rgba(vec4 yuvk)\n" -"{\n" -" vec4 rgba;\n" -" bool bt_709 = true; //TODO: pass this information from the code\n" -"\n" -" rgba.x = 1.164 * (yuvk.x - 16.0 / 255.0) + ((float(bt_709) * 1.793) + (float(!bt_709)) * (1.596)) * (yuvk.z - 128.0 / 255.0);\n" -" rgba.y = 1.164 * (yuvk.x - 16.0 / 255.0) - ((float(bt_709) * 0.534) + (float(!bt_709)) * (0.813)) * (yuvk.z - 128.0 / 255.0) - 0.213 * (yuvk.y - 128.0 / 255.0);\n" -" rgba.z = 1.164 * (yuvk.x - 16.0 / 255.0) + ((float(bt_709) * 2.115) + (float(!bt_709)) * (2.018)) * (yuvk.y - 128.0 / 255.0);\n" -" rgba.w = 1.0;\n" -" return rgba;\n" -"}\n" -"\n" -"void main() {\n" -" int width = imageSize(img_output).x;\n" -" ivec2 coords = ivec2(gl_GlobalInvocationID);\n" -" vec4 uyvy;\n" -" float PxlIdx = coords.x + coords.y * width;\n" -" vec4 yuvk;\n" -" yuvk.w = 1.0;\n" -"\n" -" if (mod(PxlIdx, 6.0) < 1.0)\n" -" {\n" -" uyvy = imageLoad(img_input, ivec2(int((coords.x + mod(coords.y,3.0)*width)*2.0/3.0), coords.y / 3));\n" -" yuvk.x = ((uyvy.y * 255.0 / 4.0) + (mod(uyvy.z * 255.0,16.0) * 64.0)) / 1023.0;\n" -" yuvk.y = (uyvy.x * 255.0 + (mod(uyvy.y * 255.0,4.0) * 256.0)) / 1023.0;\n" -" yuvk.z = ((uyvy.z * 255.0 / 16.0) + (mod(uyvy.w * 255.0,64.0) * 16.0)) / 1023.0;\n" -" }\n" -" else if (mod(PxlIdx, 6.0) < 2.0)\n" -" {\n" -" uyvy = imageLoad(img_input, ivec2(int((coords.x + mod(coords.y,3.0)*width)*2.0/3.0), coords.y / 3.0));\n" -" yuvk.y = (uyvy.x * 255.0 + (mod(uyvy.y * 255.0,4.0) * 256.0)) / 1023.0;\n" -" yuvk.z = ((uyvy.z * 255.0 / 16.0) + (mod(uyvy.w * 255.0,64.0) * 16.0)) / 1023.0;\n" -" uyvy = imageLoad(img_input, ivec2(int((coords.x + mod(coords.y,3.0)*width)*2.0/3.0) + 1, coords.y / 3.0));\n" -" yuvk.x = (uyvy.x * 255.0 + (mod(uyvy.y * 255.0,4.0) * 256.0)) / 1023.0;\n" -" }\n" -" else if (mod(PxlIdx, 6.0) < 3.0)\n" -" {\n" -" uyvy = imageLoad(img_input, ivec2(int((coords.x + mod(coords.y,3.0)*width)*2.0/3.0), coords.y / 3.0));\n" -" yuvk.x = ((uyvy.z * 255.0 / 16.0) + (mod(uyvy.w * 255.0,64.0) * 16.0)) / 1023.0;\n" -" yuvk.y = ((uyvy.y * 255.0 / 4.0) + (mod(uyvy.z * 255.0,16.0) * 64.0)) / 1023.0;\n" -" uyvy = imageLoad(img_input, ivec2(int((coords.x + mod(coords.y,3.0)*width)*2.0/3.0)+1, coords.y / 3.0));\n" -" yuvk.z = (uyvy.x * 255.0 + (mod(uyvy.y * 255.0,4.0) * 256.0)) / 1023.0;\n" -" }\n" -" else if (mod(PxlIdx, 6.0) < 4.0)\n" -" {\n" -" uyvy = imageLoad(img_input, ivec2(int((coords.x + mod(coords.y,3.0)*width)*2.0/3.0), coords.y / 3.0));\n" -" yuvk.x = ((uyvy.y * 255.0 / 4.0) + (mod(uyvy.z * 255.0,16.0) * 64.0)) / 1023.0;\n" -" yuvk.z = (uyvy.x * 255.0 + (mod(uyvy.y * 255.0,4.0) * 256.0)) / 1023.0;\n" -" uyvy = imageLoad(img_input, ivec2(int((coords.x + mod(coords.y,3.0)*width)*2.0/3.0)-1, coords.y / 3.0));\n" -" yuvk.y = ((uyvy.y * 255.0 / 4.0) + (mod(uyvy.z * 255.0,16.0) * 64.0)) / 1023.0;\n" -" }\n" -" else if (mod(PxlIdx, 6.0) < 5.0)\n" -" {\n" -" uyvy = imageLoad(img_input, ivec2(int((coords.x + mod(coords.y,3.0)*width)*2.0/3.0), coords.y / 3.0));\n" -" yuvk.y = ((uyvy.z * 255.0 / 16.0) + (mod(uyvy.w * 255.0,64.0) * 16.0)) / 1023.0;\n" -" uyvy = imageLoad(img_input, ivec2(int((coords.x + mod(coords.y,3.0)*width)*2.0/3.0)+1 , coords.y / 3.0));\n" -" yuvk.x = (uyvy.x * 255.0 + (mod(uyvy.y * 255.0,4.0) * 256.0)) / 1023.0;\n" -" yuvk.z = ((uyvy.y * 255.0 / 4.0) + (mod(uyvy.z * 255.0,16.0) * 64.0)) / 1023.0;\n" -" }\n" -" else\n" -" {\n" -" uyvy = imageLoad(img_input, ivec2(int((coords.x + mod(coords.y,3.0)*width)*2.0/3.0), coords.y / 3.0));\n" -" yuvk.x = ((uyvy.z * 255.0 / 16.0) + (mod(uyvy.w * 255.0,64.0) * 16.0)) / 1023.0;\n" -" yuvk.z = ((uyvy.y * 255.0 / 4.0) + (mod(uyvy.z * 255.0,16.0) * 64.0)) / 1023.0;\n" -" uyvy = imageLoad(img_input, ivec2(int((coords.x + mod(coords.y,3.0)*width)*2.0/3.0)-1, coords.y / 3.0));\n" -" yuvk.y = ((uyvy.z * 255.0 / 16.0) + (mod(uyvy.w * 255.0,64.0) * 16.0)) / 1023.0;\n" -" }\n" -"\n" -" imageStore(img_output, coords, yuv2rgba(yuvk));\n" -"}\n" -}; \ No newline at end of file +constexpr char const *compute_shader_422_10_le_msb = R"( +{ +#version 430 + +layout(local_size_x = 8, local_size_y = 8) in; + +layout(rgba8, binding = 0) uniform image2D img_output; +layout(rgba8, binding = 1) uniform image2D img_input; + +vec4 yuv2rgba(vec4 yuvk) +{ + vec4 rgba; + bool bt_709 = true; //TODO: pass this information from the code + + rgba.x = 1.164 * (yuvk.x - 16.0 / 255.0) + ((float(bt_709) * 1.793) + (float(!bt_709)) * (1.596)) * (yuvk.z - 128.0 / 255.0); + rgba.y = 1.164 * (yuvk.x - 16.0 / 255.0) - ((float(bt_709) * 0.534) + (float(!bt_709)) * (0.813)) * (yuvk.z - 128.0 / 255.0) - 0.213 * (yuvk.y - 128.0 / 255.0); + rgba.z = 1.164 * (yuvk.x - 16.0 / 255.0) + ((float(bt_709) * 2.115) + (float(!bt_709)) * (2.018)) * (yuvk.y - 128.0 / 255.0); + rgba.w = 1.0; + return rgba; +} + +void main() { + int width = imageSize(img_output).x; + ivec2 coords = ivec2(gl_GlobalInvocationID); + vec4 uyvy; + float PxlIdx = coords.x + coords.y * width; + vec4 yuvk; + yuvk.w = 1.0; + + if (mod(PxlIdx, 6.0) < 1.0) + { + uyvy = imageLoad(img_input, ivec2(int((coords.x + mod(coords.y,3.0)*width)*2.0/3.0), coords.y / 3)); + yuvk.x = ((uyvy.y * 255.0 / 4.0) + (mod(uyvy.z * 255.0,16.0) * 64.0)) / 1023.0; + yuvk.y = (uyvy.x * 255.0 + (mod(uyvy.y * 255.0,4.0) * 256.0)) / 1023.0; + yuvk.z = ((uyvy.z * 255.0 / 16.0) + (mod(uyvy.w * 255.0,64.0) * 16.0)) / 1023.0; + } + else if (mod(PxlIdx, 6.0) < 2.0) + { + uyvy = imageLoad(img_input, ivec2(int((coords.x + mod(coords.y,3.0)*width)*2.0/3.0), coords.y / 3.0)); + yuvk.y = (uyvy.x * 255.0 + (mod(uyvy.y * 255.0,4.0) * 256.0)) / 1023.0; + yuvk.z = ((uyvy.z * 255.0 / 16.0) + (mod(uyvy.w * 255.0,64.0) * 16.0)) / 1023.0; + uyvy = imageLoad(img_input, ivec2(int((coords.x + mod(coords.y,3.0)*width)*2.0/3.0) + 1, coords.y / 3.0)); + yuvk.x = (uyvy.x * 255.0 + (mod(uyvy.y * 255.0,4.0) * 256.0)) / 1023.0; + } + else if (mod(PxlIdx, 6.0) < 3.0) + { + uyvy = imageLoad(img_input, ivec2(int((coords.x + mod(coords.y,3.0)*width)*2.0/3.0), coords.y / 3.0)); + yuvk.x = ((uyvy.z * 255.0 / 16.0) + (mod(uyvy.w * 255.0,64.0) * 16.0)) / 1023.0; + yuvk.y = ((uyvy.y * 255.0 / 4.0) + (mod(uyvy.z * 255.0,16.0) * 64.0)) / 1023.0; + uyvy = imageLoad(img_input, ivec2(int((coords.x + mod(coords.y,3.0)*width)*2.0/3.0)+1, coords.y / 3.0)); + yuvk.z = (uyvy.x * 255.0 + (mod(uyvy.y * 255.0,4.0) * 256.0)) / 1023.0; + } + else if (mod(PxlIdx, 6.0) < 4.0) + { + uyvy = imageLoad(img_input, ivec2(int((coords.x + mod(coords.y,3.0)*width)*2.0/3.0), coords.y / 3.0)); + yuvk.x = ((uyvy.y * 255.0 / 4.0) + (mod(uyvy.z * 255.0,16.0) * 64.0)) / 1023.0; + yuvk.z = (uyvy.x * 255.0 + (mod(uyvy.y * 255.0,4.0) * 256.0)) / 1023.0; + uyvy = imageLoad(img_input, ivec2(int((coords.x + mod(coords.y,3.0)*width)*2.0/3.0)-1, coords.y / 3.0)); + yuvk.y = ((uyvy.y * 255.0 / 4.0) + (mod(uyvy.z * 255.0,16.0) * 64.0)) / 1023.0; + } + else if (mod(PxlIdx, 6.0) < 5.0) + { + uyvy = imageLoad(img_input, ivec2(int((coords.x + mod(coords.y,3.0)*width)*2.0/3.0), coords.y / 3.0)); + yuvk.y = ((uyvy.z * 255.0 / 16.0) + (mod(uyvy.w * 255.0,64.0) * 16.0)) / 1023.0; + uyvy = imageLoad(img_input, ivec2(int((coords.x + mod(coords.y,3.0)*width)*2.0/3.0)+1 , coords.y / 3.0)); + yuvk.x = (uyvy.x * 255.0 + (mod(uyvy.y * 255.0,4.0) * 256.0)) / 1023.0; + yuvk.z = ((uyvy.y * 255.0 / 4.0) + (mod(uyvy.z * 255.0,16.0) * 64.0)) / 1023.0; + } + else + { + uyvy = imageLoad(img_input, ivec2(int((coords.x + mod(coords.y,3.0)*width)*2.0/3.0), coords.y / 3.0)); + yuvk.x = ((uyvy.z * 255.0 / 16.0) + (mod(uyvy.w * 255.0,64.0) * 16.0)) / 1023.0; + yuvk.z = ((uyvy.y * 255.0 / 4.0) + (mod(uyvy.z * 255.0,16.0) * 64.0)) / 1023.0; + uyvy = imageLoad(img_input, ivec2(int((coords.x + mod(coords.y,3.0)*width)*2.0/3.0)-1, coords.y / 3.0)); + yuvk.y = ((uyvy.z * 255.0 / 16.0) + (mod(uyvy.w * 255.0,64.0) * 16.0)) / 1023.0; + } + + imageStore(img_output, coords, yuv2rgba(yuvk)); +} +)"; \ No newline at end of file diff --git a/src/ycbcr422_8_to_rgb444.shader b/src/ycbcr422_8_to_rgb444.shader index 9269030..47a1f95 100644 --- a/src/ycbcr422_8_to_rgb444.shader +++ b/src/ycbcr422_8_to_rgb444.shader @@ -1,36 +1,36 @@ -constexpr char const * compute_shader_422_8 = +constexpr char const * compute_shader_422_8 = R"( { -"#version 430\n" -"\n" -"layout(local_size_x = 8, local_size_y = 8) in;\n" -"\n" -"layout(rgba8, binding = 0) uniform image2D img_output;\n" -"layout(rgba8, binding = 1) uniform image2D img_input;\n" -"\n" -"vec4 yuv2rgba(vec4 yuvk)\n" -"{\n" -" vec4 rgba;\n" -" bool bt_709 = true; //TODO: pass this information from the code\n" -"\n" -" rgba.x = 1.164 * (yuvk.x - 16.0 / 255.0) + ((float(bt_709) * 1.793) + (float(!bt_709)) * (1.596)) * (yuvk.z - 128.0 / 255.0);\n" -" rgba.y = 1.164 * (yuvk.x - 16.0 / 255.0) - ((float(bt_709) * 0.534) + (float(!bt_709)) * (0.813)) * (yuvk.z - 128.0 / 255.0) - 0.213 * (yuvk.y - 128.0 / 255.0);\n" -" rgba.z = 1.164 * (yuvk.x - 16.0 / 255.0) + ((float(bt_709) * 2.115) + (float(!bt_709)) * (2.018)) * (yuvk.y - 128.0 / 255.0);\n" -" rgba.w = 1.0;\n" -" return rgba;\n" -"}\n" -"\n" -"void main() {\n" -" ivec2 coords = ivec2(gl_GlobalInvocationID);\n" -" vec4 uyvy = imageLoad(img_input, ivec2(coords.x / 2, coords.y));\n" -" bool odd_column = (mod(coords.x, 2) >= 1.0);\n" -" vec4 yuvk;\n" -" yuvk.x = (float(!odd_column)) * uyvy.y + (float(odd_column)) * uyvy.w;\n" -" yuvk.y = uyvy.x;\n" -" yuvk.z = uyvy.z;\n" -" yuvk.w = 1.0;\n" -"\n" -" vec4 pixel = yuv2rgba(yuvk);\n" -"\n" -" imageStore(img_output, coords, pixel);\n" -"}\n" -}; \ No newline at end of file +#version 430 + +layout(local_size_x = 8, local_size_y = 8) in; + +layout(rgba8, binding = 0) uniform image2D img_output; +layout(rgba8, binding = 1) uniform image2D img_input; + +vec4 yuv2rgba(vec4 yuvk) +{ + vec4 rgba; + bool bt_709 = true; //TODO: pass this information from the code + + rgba.x = 1.164 * (yuvk.x - 16.0 / 255.0) + ((float(bt_709) * 1.793) + (float(!bt_709)) * (1.596)) * (yuvk.z - 128.0 / 255.0); + rgba.y = 1.164 * (yuvk.x - 16.0 / 255.0) - ((float(bt_709) * 0.534) + (float(!bt_709)) * (0.813)) * (yuvk.z - 128.0 / 255.0) - 0.213 * (yuvk.y - 128.0 / 255.0); + rgba.z = 1.164 * (yuvk.x - 16.0 / 255.0) + ((float(bt_709) * 2.115) + (float(!bt_709)) * (2.018)) * (yuvk.y - 128.0 / 255.0); + rgba.w = 1.0; + return rgba; +} + +void main() { + ivec2 coords = ivec2(gl_GlobalInvocationID); + vec4 uyvy = imageLoad(img_input, ivec2(coords.x / 2, coords.y)); + bool odd_column = (mod(coords.x, 2) >= 1.0); + vec4 yuvk; + yuvk.x = (float(!odd_column)) * uyvy.y + (float(odd_column)) * uyvy.w; + yuvk.y = uyvy.x; + yuvk.z = uyvy.z; + yuvk.w = 1.0; + + vec4 pixel = yuv2rgba(yuvk); + + imageStore(img_output, coords, pixel); +} +)"; \ No newline at end of file diff --git a/src/ycbcr444_8_to_rgb444.shader b/src/ycbcr444_8_to_rgb444.shader index bd994e1..3ab3729 100644 --- a/src/ycbcr444_8_to_rgb444.shader +++ b/src/ycbcr444_8_to_rgb444.shader @@ -1,64 +1,64 @@ -constexpr char const * compute_shader_yuv_444_8 = -{ -"#version 430\n" -"\n" -"layout(local_size_x = 8, local_size_y = 8) in;\n" -"\n" -"layout(rgba8, binding = 0) uniform image2D img_output;\n" -"layout(rgba8, binding = 1) uniform image2D img_input;\n" -"\n" -"vec4 yuv2rgba(vec4 yuvk)\n" -"{\n" -" vec4 rgba;\n" -" bool bt_709 = true; //TODO: pass this information from the code\n" -"\n" -" rgba.x = 1.164 * (yuvk.x - 16.0 / 255.0) + ((float(bt_709) * 1.793) + (float(!bt_709)) * (1.596)) * (yuvk.z - 128.0 / 255.0);\n" -" rgba.y = 1.164 * (yuvk.x - 16.0 / 255.0) - ((float(bt_709) * 0.534) + (float(!bt_709)) * (0.813)) * (yuvk.z - 128.0 / 255.0) - 0.213 * (yuvk.y - 128.0 / 255.0);\n" -" rgba.z = 1.164 * (yuvk.x - 16.0 / 255.0) + ((float(bt_709) * 2.115) + (float(!bt_709)) * (2.018)) * (yuvk.y - 128.0 / 255.0);\n" -" rgba.w = 1.0;\n" -" return rgba;\n" -"}\n" -"\n" -"void main() {\n" -" int width = imageSize(img_output).x;\n" -" ivec2 coords = ivec2(gl_GlobalInvocationID);\n" -" float PxlIdx = coords.x + coords.y * width;\n" -" vec4 uyvk;\n" -" vec4 yuvk;\n" -" yuvk.w = 1.0;\n" -" if (mod(PxlIdx, 4.0) < 1.0)\n" -" {\n" -" uyvk = imageLoad(img_input, ivec2(coords.x*3.0/4.0 , coords.y));\n" -" yuvk.y = uyvk.x;\n" -" yuvk.x = uyvk.y;\n" -" yuvk.z = uyvk.z;\n" -" }\n" -" else if (mod(PxlIdx, 4.0) < 2.0)\n" -" {\n" -" uyvk = imageLoad(img_input, ivec2(int(coords.x*3.0/4.0) , coords.y));\n" -" yuvk.y = uyvk.w;\n" -" uyvk = imageLoad(img_input, ivec2(int(coords.x*3.0/4.0) + 1 , coords.y));\n" -" yuvk.x = uyvk.x;\n" -" yuvk.z = uyvk.y;\n" -" }\n" -" else if (mod(PxlIdx, 4.0) < 3.0)\n" -" {\n" -" uyvk = imageLoad(img_input, ivec2(int(coords.x*3.0/4.0) , coords.y));\n" -" yuvk.y = uyvk.z;\n" -" yuvk.x = uyvk.w;\n" -" uyvk = imageLoad(img_input, ivec2(int(coords.x*3.0/4.0) + 1 , coords.y));\n" -" yuvk.z = uyvk.x;\n" -" }\n" -" else if (mod(PxlIdx, 4.0) < 4.0)\n" -" {\n" -" uyvk = imageLoad(img_input, ivec2(int(coords.x*3.0/4.0) , coords.y));\n" -" yuvk.y = uyvk.y;\n" -" yuvk.x = uyvk.z;\n" -" yuvk.z = uyvk.w;\n" -" }\n" -"\n" -" vec4 pixel = yuv2rgba(yuvk);\n" -"\n" -" imageStore(img_output, coords, pixel);\n" -"}\n" -}; \ No newline at end of file +constexpr char const * compute_shader_yuv_444_8 = R"( +{ +#version 430 + +layout(local_size_x = 8, local_size_y = 8) in; + +layout(rgba8, binding = 0) uniform image2D img_output; +layout(rgba8, binding = 1) uniform image2D img_input; + +vec4 yuv2rgba(vec4 yuvk) +{ + vec4 rgba; + bool bt_709 = true; //TODO: pass this information from the code + + rgba.x = 1.164 * (yuvk.x - 16.0 / 255.0) + ((float(bt_709) * 1.793) + (float(!bt_709)) * (1.596)) * (yuvk.z - 128.0 / 255.0); + rgba.y = 1.164 * (yuvk.x - 16.0 / 255.0) - ((float(bt_709) * 0.534) + (float(!bt_709)) * (0.813)) * (yuvk.z - 128.0 / 255.0) - 0.213 * (yuvk.y - 128.0 / 255.0); + rgba.z = 1.164 * (yuvk.x - 16.0 / 255.0) + ((float(bt_709) * 2.115) + (float(!bt_709)) * (2.018)) * (yuvk.y - 128.0 / 255.0); + rgba.w = 1.0; + return rgba; +} + +void main() { + int width = imageSize(img_output).x; + ivec2 coords = ivec2(gl_GlobalInvocationID); + float PxlIdx = coords.x + coords.y * width; + vec4 uyvk; + vec4 yuvk; + yuvk.w = 1.0; + if (mod(PxlIdx, 4.0) < 1.0) + { + uyvk = imageLoad(img_input, ivec2(coords.x*3.0/4.0 , coords.y)); + yuvk.y = uyvk.x; + yuvk.x = uyvk.y; + yuvk.z = uyvk.z; + } + else if (mod(PxlIdx, 4.0) < 2.0) + { + uyvk = imageLoad(img_input, ivec2(int(coords.x*3.0/4.0) , coords.y)); + yuvk.y = uyvk.w; + uyvk = imageLoad(img_input, ivec2(int(coords.x*3.0/4.0) + 1 , coords.y)); + yuvk.x = uyvk.x; + yuvk.z = uyvk.y; + } + else if (mod(PxlIdx, 4.0) < 3.0) + { + uyvk = imageLoad(img_input, ivec2(int(coords.x*3.0/4.0) , coords.y)); + yuvk.y = uyvk.z; + yuvk.x = uyvk.w; + uyvk = imageLoad(img_input, ivec2(int(coords.x*3.0/4.0) + 1 , coords.y)); + yuvk.z = uyvk.x; + } + else if (mod(PxlIdx, 4.0) < 4.0) + { + uyvk = imageLoad(img_input, ivec2(int(coords.x*3.0/4.0) , coords.y)); + yuvk.y = uyvk.y; + yuvk.x = uyvk.z; + yuvk.z = uyvk.w; + } + + vec4 pixel = yuv2rgba(yuvk); + + imageStore(img_output, coords, pixel); +} +)";