summaryrefslogtreecommitdiff
path: root/kms++util/src/conv-yuv-planar.h
diff options
context:
space:
mode:
Diffstat (limited to 'kms++util/src/conv-yuv-planar.h')
-rw-r--r--kms++util/src/conv-yuv-planar.h214
1 files changed, 0 insertions, 214 deletions
diff --git a/kms++util/src/conv-yuv-planar.h b/kms++util/src/conv-yuv-planar.h
deleted file mode 100644
index b8e9247..0000000
--- a/kms++util/src/conv-yuv-planar.h
+++ /dev/null
@@ -1,214 +0,0 @@
-#pragma once
-
-#include <vector>
-
-#include <kms++/framebuffer.h>
-#include <kms++util/color16.h>
-
-#include "conv-common.h"
-
-namespace kms
-{
-/* YUV Planar */
-
-template<ComponentType P1, ComponentType P2, size_t HSubUV = 1, size_t VSubUV = 1>
-class YUV_Planar_Layout
- : public FormatLayout<
- PlaneLayout<uint8_t, ComponentLayout<ComponentType::Y, 8, 0>>,
- PlaneLayout<uint8_t, ComponentLayout<P1, 8, 0>>,
- PlaneLayout<uint8_t, ComponentLayout<P2, 8, 0>>
- >
-{
-public:
- static constexpr std::array<ComponentType, 2> uv_order = { P1, P2 };
- static constexpr size_t h_sub = HSubUV;
- static constexpr size_t v_sub = VSubUV;
-
- template<ComponentType P>
- static constexpr size_t find_plane()
- {
- return 1 + (std::ranges::find(uv_order, P) - uv_order.begin());
- }
-
- static constexpr size_t y_plane = 0; // Y is always plane 0
- static constexpr size_t cb_plane = find_plane<ComponentType::Cb>();
- static constexpr size_t cr_plane = find_plane<ComponentType::Cr>();
-};
-
-using YUV444_Layout = YUV_Planar_Layout<ComponentType::Cb, ComponentType::Cr>;
-using YVU444_Layout = YUV_Planar_Layout<ComponentType::Cr, ComponentType::Cb>;
-using YUV422_Layout = YUV_Planar_Layout<ComponentType::Cb, ComponentType::Cr, 2, 1>;
-using YVU422_Layout = YUV_Planar_Layout<ComponentType::Cr, ComponentType::Cb, 2, 1>;
-using YUV420_Layout = YUV_Planar_Layout<ComponentType::Cb, ComponentType::Cr, 2, 2>;
-using YVU420_Layout = YUV_Planar_Layout<ComponentType::Cr, ComponentType::Cb, 2, 2>;
-
-template<typename Format>
-class YUVPlanarWriter
-{
- using YLayout = typename Format::template plane<Format::y_plane>;
- using CbLayout = typename Format::template plane<Format::cb_plane>;
- using CrLayout = typename Format::template plane<Format::cr_plane>;
-
- using TY = typename YLayout::storage_type;
- using TCb = typename CbLayout::storage_type;
- using TCr = typename CrLayout::storage_type;
-public:
- static void write_pattern(IFramebuffer& fb, size_t start_y, size_t end_y,
- auto&& generate_line)
- {
- assert(start_y % Format::v_sub == 0);
- assert((end_y + 1) % Format::v_sub == 0);
-
- // Line buffers
- std::vector<YUV16> linebuf_storage(fb.width() * Format::v_sub);
- auto linebuf = md::mdspan(linebuf_storage.data(), Format::v_sub, fb.width());
-
- // Views to all planes
- auto y_buf = make_strided_fb_view<TY>(fb.map(Format::y_plane), fb.height(),
- fb.width(), fb.stride(Format::y_plane));
-
- auto cb_buf = make_strided_fb_view<TCb>(fb.map(Format::cb_plane),
- fb.height() / Format::v_sub,
- fb.width() / Format::h_sub,
- fb.stride(Format::cb_plane));
-
- auto cr_buf = make_strided_fb_view<TCr>(fb.map(Format::cr_plane),
- fb.height() / Format::v_sub,
- fb.width() / Format::h_sub,
- fb.stride(Format::cr_plane));
-
- for (size_t y_src = start_y; y_src <= end_y; y_src++) {
- size_t y_offset = y_src % Format::v_sub;
-
- if (y_offset == 0) {
- // Fill line buffers
- for (size_t buf_y = 0; buf_y < Format::v_sub; buf_y++) {
- auto line = md::submdspan(linebuf, buf_y, md::full_extent);
- std::span<YUV16> span(line.data_handle(), line.size());
- generate_line(y_src + buf_y, span);
- }
- }
-
- // Write Y plane
- write_y_line(y_buf, y_src, linebuf, y_offset);
-
- // Write Cb/Cr planes if we're at a subsampling boundary
- if (y_offset == 0)
- write_uv_line(cb_buf, cr_buf, linebuf, y_src);
- }
- }
-
- static void write_lines(IFramebuffer& fb, size_t start_y, size_t end_y,
- Is2Dspan<YUV16> auto&& lines)
- {
- const size_t height = end_y - start_y + 1;
-
- if (lines.extent(0) < height || lines.extent(1) < fb.width())
- throw std::invalid_argument("Source line buffer too small");
-
- assert(start_y % Format::v_sub == 0);
- assert((end_y + 1) % Format::v_sub == 0);
-
- // Views to all planes
- auto y_buf = make_strided_fb_view<TY>(fb.map(Format::y_plane), fb.height(),
- fb.width(), fb.stride(Format::y_plane));
-
- auto cb_buf = make_strided_fb_view<TCb>(fb.map(Format::cb_plane),
- fb.height() / Format::v_sub,
- fb.width() / Format::h_sub,
- fb.stride(Format::cb_plane));
-
- auto cr_buf = make_strided_fb_view<TCr>(fb.map(Format::cr_plane),
- fb.height() / Format::v_sub,
- fb.width() / Format::h_sub,
- fb.stride(Format::cr_plane));
-
- for (size_t y_src = start_y; y_src <= end_y; y_src++) {
- size_t y_offset = y_src % Format::v_sub;
-
- // Write Y plane
- write_y_line(y_buf, y_src, lines, y_offset);
-
- // Write Cb/Cr planes if we're at a subsampling boundary
- if (y_offset == 0)
- write_uv_line(cb_buf, cr_buf, lines, y_src);
- }
- }
-
-private:
- template<typename YBuf>
- static void write_y_line(YBuf& y_buf, size_t y_src, auto& linebuf, size_t y_offset)
- {
- for (size_t x = 0; x < linebuf.extent(1); x++)
- y_buf(y_src, x) = YLayout::pack(linebuf(y_offset, x).y >> 8);
- }
-
- template<typename UVBuf>
- static void write_uv_line(UVBuf& cb_buf, UVBuf& cr_buf, auto& linebuf, size_t y_src)
- {
- const size_t uv_y = y_src / Format::v_sub;
-
- for (size_t x = 0; x < linebuf.extent(1); x += Format::h_sub) {
- // Average subsampled region
- uint32_t u_sum = 0, v_sum = 0;
- for (size_t y = 0; y < Format::v_sub; y++) {
- for (size_t x_off = 0; x_off < Format::h_sub; x_off++) {
- u_sum += linebuf(y, x + x_off).u;
- v_sum += linebuf(y, x + x_off).v;
- }
- }
-
- const size_t total_samples = Format::h_sub * Format::v_sub;
- const size_t uv_x = x / Format::h_sub;
-
- cb_buf(uv_y, uv_x) = CbLayout::pack(u_sum / total_samples >> 8);
- cr_buf(uv_y, uv_x) = CrLayout::pack(v_sum / total_samples >> 8);
- }
- }
-
-public:
- static void read_lines(IFramebuffer& fb, size_t start_y, size_t end_y,
- Is2Dspan<YUV16> auto&& dest)
- {
- const size_t height = end_y - start_y + 1;
-
- if (dest.extent(0) < height || dest.extent(1) < fb.width())
- throw std::invalid_argument("Destination line buffer too small");
-
- assert(start_y % Format::v_sub == 0);
- assert((end_y + 1) % Format::v_sub == 0);
-
- auto y_buf = make_strided_fb_view<const TY>(fb.map(Format::y_plane), fb.height(),
- fb.width(), fb.stride(Format::y_plane));
-
- auto cb_buf = make_strided_fb_view<const TCb>(fb.map(Format::cb_plane),
- fb.height() / Format::v_sub,
- fb.width() / Format::h_sub,
- fb.stride(Format::cb_plane));
-
- auto cr_buf = make_strided_fb_view<const TCr>(fb.map(Format::cr_plane),
- fb.height() / Format::v_sub,
- fb.width() / Format::h_sub,
- fb.stride(Format::cr_plane));
-
- for (size_t y = start_y; y <= end_y; y++) {
- for (size_t x = 0; x < fb.width(); x++) {
- const auto y_val = YLayout::unpack(y_buf(y, x))[0];
-
- const size_t uv_y = y / Format::v_sub;
- const size_t uv_x = x / Format::h_sub;
-
- const auto u_val = CbLayout::unpack(cb_buf(uv_y, uv_x))[0];
- const auto v_val = CrLayout::unpack(cr_buf(uv_y, uv_x))[0];
-
- dest(y - start_y, x) = YUV16 {
- static_cast<uint16_t>(y_val << 8),
- static_cast<uint16_t>(u_val << 8),
- static_cast<uint16_t>(v_val << 8)
- };
- }
- }
- }
-};
-
-} // namespace kms