pip based
This commit is contained in:
+102
@@ -1,8 +1,10 @@
|
||||
#pragma once
|
||||
#include <algorithm>
|
||||
#include <array>
|
||||
#include <cstddef>
|
||||
#include <cstdint>
|
||||
#include <cstring>
|
||||
#include <vector>
|
||||
|
||||
namespace dmf::v210 {
|
||||
|
||||
@@ -173,4 +175,104 @@ inline void YUV422P10toV210(
|
||||
}
|
||||
}
|
||||
|
||||
// Unpack one V210 row into planar uint16_t Y (width values),
|
||||
// Cb and Cr (width/2 values each). Width must be a multiple of 6.
|
||||
inline void unpack_row(const uint8_t* src, int width,
|
||||
uint16_t* Y, uint16_t* Cb, uint16_t* Cr)
|
||||
{
|
||||
const auto* w = reinterpret_cast<const uint32_t*>(src);
|
||||
const int blocks = width / 6;
|
||||
for (int b = 0; b < blocks; ++b, w += 4) {
|
||||
const int x = b * 6;
|
||||
Cb[x/2] = (w[0] >> 0) & 0x3FF;
|
||||
Y[x] = (w[0] >> 10) & 0x3FF;
|
||||
Cr[x/2] = (w[0] >> 20) & 0x3FF;
|
||||
Y[x+1] = (w[1] >> 0) & 0x3FF;
|
||||
Cb[x/2+1] = (w[1] >> 10) & 0x3FF;
|
||||
Y[x+2] = (w[1] >> 20) & 0x3FF;
|
||||
Cr[x/2+1] = (w[2] >> 0) & 0x3FF;
|
||||
Y[x+3] = (w[2] >> 10) & 0x3FF;
|
||||
Cb[x/2+2] = (w[2] >> 20) & 0x3FF;
|
||||
Y[x+4] = (w[3] >> 0) & 0x3FF;
|
||||
Cr[x/2+2] = (w[3] >> 10) & 0x3FF;
|
||||
Y[x+5] = (w[3] >> 20) & 0x3FF;
|
||||
}
|
||||
}
|
||||
|
||||
// Scale the inset V210 frame into a rectangular region of dst using bilinear
|
||||
// interpolation. pip_x and pip_w must be multiples of 6 (V210 alignment).
|
||||
// Workspace vectors are passed in to avoid per-call heap allocation.
|
||||
inline void scale_and_overlay(
|
||||
const uint8_t* inset, uint32_t inset_stride, int inset_w, int inset_h,
|
||||
uint8_t* dst, uint32_t dst_stride,
|
||||
int pip_x, int pip_y, int pip_w, int pip_h,
|
||||
std::vector<uint16_t>& Y0_buf, std::vector<uint16_t>& Y1_buf,
|
||||
std::vector<uint16_t>& Cb0_buf, std::vector<uint16_t>& Cb1_buf,
|
||||
std::vector<uint16_t>& Cr0_buf, std::vector<uint16_t>& Cr1_buf)
|
||||
{
|
||||
Y0_buf.resize(inset_w); Y1_buf.resize(inset_w);
|
||||
Cb0_buf.resize(inset_w / 2); Cb1_buf.resize(inset_w / 2);
|
||||
Cr0_buf.resize(inset_w / 2); Cr1_buf.resize(inset_w / 2);
|
||||
|
||||
const int out_blocks = pip_w / 6;
|
||||
const int dst_x_bytes = (pip_x / 6) * 16;
|
||||
const float inv_pip_h = static_cast<float>(inset_h) / pip_h;
|
||||
const float inv_pip_w = static_cast<float>(inset_w) / pip_w;
|
||||
const float inv_pip_cw = static_cast<float>(inset_w / 2) / (pip_w / 2);
|
||||
|
||||
int cur_row0 = -1, cur_row1 = -1;
|
||||
|
||||
for (int dy = 0; dy < pip_h; ++dy) {
|
||||
const float sy = (dy + 0.5f) * inv_pip_h - 0.5f;
|
||||
const int sy0 = std::max(0, static_cast<int>(sy));
|
||||
const int sy1 = std::min(inset_h - 1, sy0 + 1);
|
||||
const float fy = sy - static_cast<float>(sy0);
|
||||
|
||||
if (sy0 != cur_row0) {
|
||||
unpack_row(inset + static_cast<size_t>(sy0) * inset_stride, inset_w,
|
||||
Y0_buf.data(), Cb0_buf.data(), Cr0_buf.data());
|
||||
cur_row0 = sy0;
|
||||
}
|
||||
if (sy1 != cur_row1) {
|
||||
unpack_row(inset + static_cast<size_t>(sy1) * inset_stride, inset_w,
|
||||
Y1_buf.data(), Cb1_buf.data(), Cr1_buf.data());
|
||||
cur_row1 = sy1;
|
||||
}
|
||||
|
||||
uint8_t* dst_row = dst + static_cast<size_t>(pip_y + dy) * dst_stride + dst_x_bytes;
|
||||
|
||||
for (int b = 0; b < out_blocks; ++b) {
|
||||
const int bx = b * 6;
|
||||
uint16_t Y[6], Cb[3], Cr[3];
|
||||
|
||||
for (int i = 0; i < 6; ++i) {
|
||||
const float sx = (bx + i + 0.5f) * inv_pip_w - 0.5f;
|
||||
const int sx0 = std::max(0, static_cast<int>(sx));
|
||||
const int sx1 = std::min(inset_w - 1, sx0 + 1);
|
||||
const float fx = sx - static_cast<float>(sx0);
|
||||
Y[i] = static_cast<uint16_t>(
|
||||
Y0_buf[sx0] * (1-fx) * (1-fy) + Y0_buf[sx1] * fx * (1-fy) +
|
||||
Y1_buf[sx0] * (1-fx) * fy + Y1_buf[sx1] * fx * fy + 0.5f);
|
||||
}
|
||||
for (int i = 0; i < 3; ++i) {
|
||||
const float cx = (b * 3 + i + 0.5f) * inv_pip_cw - 0.5f;
|
||||
const int cx0 = std::max(0, static_cast<int>(cx));
|
||||
const int cx1 = std::min(inset_w / 2 - 1, cx0 + 1);
|
||||
const float cfx = cx - static_cast<float>(cx0);
|
||||
Cb[i] = static_cast<uint16_t>(
|
||||
Cb0_buf[cx0]*(1-cfx)*(1-fy) + Cb0_buf[cx1]*cfx*(1-fy) +
|
||||
Cb1_buf[cx0]*(1-cfx)* fy + Cb1_buf[cx1]*cfx* fy + 0.5f);
|
||||
Cr[i] = static_cast<uint16_t>(
|
||||
Cr0_buf[cx0]*(1-cfx)*(1-fy) + Cr0_buf[cx1]*cfx*(1-fy) +
|
||||
Cr1_buf[cx0]*(1-cfx)* fy + Cr1_buf[cx1]*cfx* fy + 0.5f);
|
||||
}
|
||||
|
||||
pack_block(dst_row + b * 16,
|
||||
{0, Cb[0], Cr[0]}, Y[0], Y[1],
|
||||
{0, Cb[1], Cr[1]}, Y[2], Y[3],
|
||||
{0, Cb[2], Cr[2]}, Y[4], Y[5]);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
} // namespace dmf::v210
|
||||
|
||||
Reference in New Issue
Block a user