190 lines
6.4 KiB
C++
190 lines
6.4 KiB
C++
#pragma once
|
|
|
|
#include <cstdint>
|
|
|
|
struct RgbColor
|
|
{
|
|
uint8_t r = 0;
|
|
uint8_t g = 0;
|
|
uint8_t b = 0;
|
|
};
|
|
|
|
inline uint32_t packRgba8(RgbColor color)
|
|
{
|
|
constexpr uint8_t alpha = 255;
|
|
|
|
return (alpha << 24) |
|
|
(color.b << 16) |
|
|
(color.g << 8) |
|
|
color.r;
|
|
}
|
|
|
|
inline uint8_t clampUint8(int32_t v)
|
|
{
|
|
return static_cast<uint8_t>(
|
|
v < 0 ? 0 : (v > 255 ? 255 : v)
|
|
);
|
|
}
|
|
|
|
inline uint32_t v210LineStride(uint32_t width)
|
|
{
|
|
uint32_t groups = (width + 5) / 6;
|
|
uint32_t rawBytes = groups * 16;
|
|
return ((rawBytes + 127) / 128) * 128;
|
|
}
|
|
|
|
inline void decodeV210Line(
|
|
const uint8_t* lineData,
|
|
uint32_t* rgbaLine,
|
|
uint32_t width)
|
|
{
|
|
for (uint32_t x = 0; x < width; ++x)
|
|
{
|
|
uint32_t group = x / 6;
|
|
uint32_t pos = x % 6;
|
|
|
|
const uint32_t baseOffset = group * 16;
|
|
uint32_t w0;
|
|
uint32_t w1;
|
|
uint32_t w2;
|
|
uint32_t w3;
|
|
|
|
const uint8_t* p = lineData + baseOffset;
|
|
w0 = static_cast<uint32_t>(p[0]) |
|
|
(static_cast<uint32_t>(p[1]) << 8) |
|
|
(static_cast<uint32_t>(p[2]) << 16) |
|
|
(static_cast<uint32_t>(p[3]) << 24);
|
|
w1 = static_cast<uint32_t>(p[4]) |
|
|
(static_cast<uint32_t>(p[5]) << 8) |
|
|
(static_cast<uint32_t>(p[6]) << 16) |
|
|
(static_cast<uint32_t>(p[7]) << 24);
|
|
w2 = static_cast<uint32_t>(p[8]) |
|
|
(static_cast<uint32_t>(p[9]) << 8) |
|
|
(static_cast<uint32_t>(p[10]) << 16) |
|
|
(static_cast<uint32_t>(p[11]) << 24);
|
|
w3 = static_cast<uint32_t>(p[12]) |
|
|
(static_cast<uint32_t>(p[13]) << 8) |
|
|
(static_cast<uint32_t>(p[14]) << 16) |
|
|
(static_cast<uint32_t>(p[15]) << 24);
|
|
|
|
uint32_t cb0 = (w0 >> 0) & 0x3FF;
|
|
uint32_t y0 = (w0 >> 10) & 0x3FF;
|
|
uint32_t cr0 = (w0 >> 20) & 0x3FF;
|
|
uint32_t y1 = (w1 >> 0) & 0x3FF;
|
|
uint32_t cb2 = (w1 >> 10) & 0x3FF;
|
|
uint32_t y2 = (w1 >> 20) & 0x3FF;
|
|
uint32_t cr2 = (w2 >> 0) & 0x3FF;
|
|
uint32_t y3 = (w2 >> 10) & 0x3FF;
|
|
uint32_t cb4 = (w2 >> 20) & 0x3FF;
|
|
uint32_t y4 = (w3 >> 0) & 0x3FF;
|
|
uint32_t cr4 = (w3 >> 10) & 0x3FF;
|
|
uint32_t y5 = (w3 >> 20) & 0x3FF;
|
|
|
|
uint32_t y10;
|
|
uint32_t cb10;
|
|
uint32_t cr10;
|
|
|
|
switch (pos)
|
|
{
|
|
case 0: y10 = y0; cb10 = cb0; cr10 = cr0; break;
|
|
case 1: y10 = y1; cb10 = cb0; cr10 = cr0; break;
|
|
case 2: y10 = y2; cb10 = cb2; cr10 = cr2; break;
|
|
case 3: y10 = y3; cb10 = cb2; cr10 = cr2; break;
|
|
case 4: y10 = y4; cb10 = cb4; cr10 = cr4; break;
|
|
case 5: y10 = y5; cb10 = cb4; cr10 = cr4; break;
|
|
default: y10 = y0; cb10 = cb0; cr10 = cr0; break;
|
|
}
|
|
|
|
int32_t yp = (static_cast<int32_t>(y10) - 64) >> 2;
|
|
int32_t cbp = (static_cast<int32_t>(cb10) - 512) >> 2;
|
|
int32_t crp = (static_cast<int32_t>(cr10) - 512) >> 2;
|
|
|
|
int32_t r = (298 * yp + 459 * crp + 128) >> 8;
|
|
int32_t g = (298 * yp - 137 * crp - 55 * cbp + 128) >> 8;
|
|
int32_t b = (298 * yp + 541 * cbp + 128) >> 8;
|
|
|
|
rgbaLine[x] = packRgba8({clampUint8(r), clampUint8(g), clampUint8(b)});
|
|
}
|
|
}
|
|
|
|
inline void convertV210ToRgba(
|
|
const uint8_t* v210Data,
|
|
uint32_t srcWidth,
|
|
uint32_t srcHeight,
|
|
uint32_t srcStride,
|
|
uint32_t* rgbaData,
|
|
uint32_t dstWidth,
|
|
uint32_t dstHeight)
|
|
{
|
|
for (uint32_t dy = 0; dy < dstHeight; ++dy)
|
|
{
|
|
uint32_t sy = dy * srcHeight / dstHeight;
|
|
|
|
const uint8_t* srcLine = v210Data + sy * srcStride;
|
|
|
|
for (uint32_t dx = 0; dx < dstWidth; ++dx)
|
|
{
|
|
uint32_t sx = dx * srcWidth / dstWidth;
|
|
|
|
uint32_t group = sx / 6;
|
|
uint32_t pos = sx % 6;
|
|
|
|
const uint8_t* p = srcLine + group * 16;
|
|
uint32_t w0 = static_cast<uint32_t>(p[0]) |
|
|
(static_cast<uint32_t>(p[1]) << 8) |
|
|
(static_cast<uint32_t>(p[2]) << 16) |
|
|
(static_cast<uint32_t>(p[3]) << 24);
|
|
uint32_t w1 = static_cast<uint32_t>(p[4]) |
|
|
(static_cast<uint32_t>(p[5]) << 8) |
|
|
(static_cast<uint32_t>(p[6]) << 16) |
|
|
(static_cast<uint32_t>(p[7]) << 24);
|
|
uint32_t w2 = static_cast<uint32_t>(p[8]) |
|
|
(static_cast<uint32_t>(p[9]) << 8) |
|
|
(static_cast<uint32_t>(p[10]) << 16) |
|
|
(static_cast<uint32_t>(p[11]) << 24);
|
|
uint32_t w3 = static_cast<uint32_t>(p[12]) |
|
|
(static_cast<uint32_t>(p[13]) << 8) |
|
|
(static_cast<uint32_t>(p[14]) << 16) |
|
|
(static_cast<uint32_t>(p[15]) << 24);
|
|
|
|
uint32_t cb0 = (w0 >> 0) & 0x3FF;
|
|
uint32_t y0 = (w0 >> 10) & 0x3FF;
|
|
uint32_t cr0 = (w0 >> 20) & 0x3FF;
|
|
uint32_t y1 = (w1 >> 0) & 0x3FF;
|
|
uint32_t cb2 = (w1 >> 10) & 0x3FF;
|
|
uint32_t y2 = (w1 >> 20) & 0x3FF;
|
|
uint32_t cr2 = (w2 >> 0) & 0x3FF;
|
|
uint32_t y3 = (w2 >> 10) & 0x3FF;
|
|
uint32_t cb4 = (w2 >> 20) & 0x3FF;
|
|
uint32_t y4 = (w3 >> 0) & 0x3FF;
|
|
uint32_t cr4 = (w3 >> 10) & 0x3FF;
|
|
uint32_t y5 = (w3 >> 20) & 0x3FF;
|
|
|
|
uint32_t y10;
|
|
uint32_t cb10;
|
|
uint32_t cr10;
|
|
|
|
switch (pos)
|
|
{
|
|
case 0: y10 = y0; cb10 = cb0; cr10 = cr0; break;
|
|
case 1: y10 = y1; cb10 = cb0; cr10 = cr0; break;
|
|
case 2: y10 = y2; cb10 = cb2; cr10 = cr2; break;
|
|
case 3: y10 = y3; cb10 = cb2; cr10 = cr2; break;
|
|
case 4: y10 = y4; cb10 = cb4; cr10 = cr4; break;
|
|
case 5: y10 = y5; cb10 = cb4; cr10 = cr4; break;
|
|
default: y10 = y0; cb10 = cb0; cr10 = cr0; break;
|
|
}
|
|
|
|
int32_t yp = (static_cast<int32_t>(y10) - 64) >> 2;
|
|
int32_t cbp = (static_cast<int32_t>(cb10) - 512) >> 2;
|
|
int32_t crp = (static_cast<int32_t>(cr10) - 512) >> 2;
|
|
|
|
int32_t r = (298 * yp + 459 * crp + 128) >> 8;
|
|
int32_t g = (298 * yp - 137 * crp - 55 * cbp + 128) >> 8;
|
|
int32_t b = (298 * yp + 541 * cbp + 128) >> 8;
|
|
|
|
rgbaData[dy * dstWidth + dx] = packRgba8(
|
|
{clampUint8(r), clampUint8(g), clampUint8(b)});
|
|
}
|
|
}
|
|
} |