MXVK Vulkan Framework 0.24.0
C++20 Vulkan rendering framework for practical 2D and 3D application development with SDL3.
Loading...
Searching...
No Matches
anonymous_namespace{mxwrite.cpp} Namespace Reference

Functions

uint16_t clamp10 (float v)
void convertBt2020Rgba16EncodedToYuv420p10 (const uint16_t *rgba, int src_stride_shorts, uint16_t *y_plane, int y_stride_shorts, uint16_t *u_plane, int u_stride_shorts, uint16_t *v_plane, int v_stride_shorts, int width, int height)
void convertRgbaToBt2020PqYuv420p10 (const uint8_t *rgba, int src_stride_bytes, uint16_t *y_plane, int y_stride_shorts, uint16_t *u_plane, int u_stride_shorts, uint16_t *v_plane, int v_stride_shorts, int width, int height)
bool is_valid_x264_preset (const std::string &p)
std::string lowercase_ascii (std::string text)
float pqOetf (float L)
float srgbEotf (float v)
const char * x264_preset_to_nvenc (const std::string &p)

Variables

constexpr float kPqC1 = 3424.0f / 4096.0f
constexpr float kPqC2 = (2413.0f / 4096.0f) * 32.0f
constexpr float kPqC3 = (2392.0f / 4096.0f) * 32.0f
constexpr float kPqM1 = 2610.0f / 16384.0f
constexpr float kPqM2 = (2523.0f / 4096.0f) * 128.0f
constexpr float kSdrRefFraction = 100.0f / 10000.0f

Function Documentation

◆ clamp10()

uint16_t anonymous_namespace{mxwrite.cpp}::clamp10 ( float v)
inline

Definition at line 50 of file mxwrite.cpp.

50 {
51 if (v < 0.0f) v = 0.0f;
52 if (v > 1023.0f) v = 1023.0f;
53 return static_cast<uint16_t>(v + 0.5f);
54}

◆ convertBt2020Rgba16EncodedToYuv420p10()

void anonymous_namespace{mxwrite.cpp}::convertBt2020Rgba16EncodedToYuv420p10 ( const uint16_t * rgba,
int src_stride_shorts,
uint16_t * y_plane,
int y_stride_shorts,
uint16_t * u_plane,
int u_stride_shorts,
uint16_t * v_plane,
int v_stride_shorts,
int width,
int height )

Definition at line 139 of file mxwrite.cpp.

144 {
145 constexpr float kKr = 0.2627f;
146 constexpr float kKg = 0.6780f;
147 constexpr float kKb = 0.0593f;
148 constexpr float kPbDiv = 1.0f / 1.8814f;
149 constexpr float kPrDiv = 1.0f / 1.4746f;
150 constexpr float kInv65535 = 1.0f / 65535.0f;
151
152 for (int y = 0; y < height; y += 2) {
153 const int y1 = std::min(y + 1, height - 1);
154 const uint16_t *row0 = rgba + y * src_stride_shorts;
155 const uint16_t *row1 = rgba + y1 * src_stride_shorts;
156 uint16_t *yr0 = y_plane + y * y_stride_shorts;
157 uint16_t *yr1 = y_plane + y1 * y_stride_shorts;
158 uint16_t *ur = u_plane + (y / 2) * u_stride_shorts;
159 uint16_t *vr = v_plane + (y / 2) * v_stride_shorts;
160
161 for (int x = 0; x < width; x += 2) {
162 const int x1 = std::min(x + 1, width - 1);
163
164 auto load = [&](const uint16_t *px, float &Y, float &U, float &V) {
165 const float rp = px[0] * kInv65535;
166 const float gp = px[1] * kInv65535;
167 const float bp = px[2] * kInv65535;
168 Y = kKr * rp + kKg * gp + kKb * bp;
169 U = (bp - Y) * kPbDiv;
170 V = (rp - Y) * kPrDiv;
171 };
172
173 float Y00, U00, V00;
174 float Y01, U01, V01;
175 float Y10, U10, V10;
176 float Y11, U11, V11;
177 load(row0 + x * 4, Y00, U00, V00);
178 load(row0 + x1 * 4, Y01, U01, V01);
179 load(row1 + x * 4, Y10, U10, V10);
180 load(row1 + x1 * 4, Y11, U11, V11);
181
182 yr0[x] = clamp10(Y00 * 876.0f + 64.0f);
183 yr0[x1] = clamp10(Y01 * 876.0f + 64.0f);
184 yr1[x] = clamp10(Y10 * 876.0f + 64.0f);
185 yr1[x1] = clamp10(Y11 * 876.0f + 64.0f);
186
187 const float Uavg = 0.25f * (U00 + U01 + U10 + U11);
188 const float Vavg = 0.25f * (V00 + V01 + V10 + V11);
189 ur[x / 2] = clamp10(Uavg * 896.0f + 512.0f);
190 vr[x / 2] = clamp10(Vavg * 896.0f + 512.0f);
191 }
192 }
193}

◆ convertRgbaToBt2020PqYuv420p10()

void anonymous_namespace{mxwrite.cpp}::convertRgbaToBt2020PqYuv420p10 ( const uint8_t * rgba,
int src_stride_bytes,
uint16_t * y_plane,
int y_stride_shorts,
uint16_t * u_plane,
int u_stride_shorts,
uint16_t * v_plane,
int v_stride_shorts,
int width,
int height )

Definition at line 60 of file mxwrite.cpp.

65 {
66 // BT.2020 non-constant luminance RGB->YUV (limited range).
67 // E'Y = 0.2627*R + 0.6780*G + 0.0593*B
68 // E'Pb = (B - Y) / 1.8814
69 // E'Pr = (R - Y) / 1.4746
70 // Limited 10-bit: Y: 0..1 -> 64..940 (range 876), UV: -0.5..0.5 -> 64..960 (range 896, center 512).
71 constexpr float kKr = 0.2627f;
72 constexpr float kKg = 0.6780f;
73 constexpr float kKb = 0.0593f;
74 constexpr float kPbDiv = 1.0f / 1.8814f;
75 constexpr float kPrDiv = 1.0f / 1.4746f;
76
77 for (int y = 0; y < height; y += 2) {
78 const int y1 = std::min(y + 1, height - 1);
79 const uint8_t *row0 = rgba + y * src_stride_bytes;
80 const uint8_t *row1 = rgba + y1 * src_stride_bytes;
81 uint16_t *yr0 = y_plane + y * y_stride_shorts;
82 uint16_t *yr1 = y_plane + y1 * y_stride_shorts;
83 uint16_t *ur = u_plane + (y / 2) * u_stride_shorts;
84 uint16_t *vr = v_plane + (y / 2) * v_stride_shorts;
85
86 for (int x = 0; x < width; x += 2) {
87 const int x1 = std::min(x + 1, width - 1);
88
89 // Load 2x2 block of sRGB 8-bit pixels.
90 auto loadPq = [](const uint8_t *px,
91 float &Y, float &U, float &V) {
92 // sRGB 8-bit -> linear [0,1]
93 const float r = srgbEotf(px[0] * (1.0f / 255.0f));
94 const float g = srgbEotf(px[1] * (1.0f / 255.0f));
95 const float b = srgbEotf(px[2] * (1.0f / 255.0f));
96 // Scale SDR linear [0,1] (reference 100 nits) to PQ fractional.
97 const float rL = r * kSdrRefFraction;
98 const float gL = g * kSdrRefFraction;
99 const float bL = b * kSdrRefFraction;
100 // PQ encode per channel (RGB PQ).
101 const float rp = pqOetf(rL);
102 const float gp = pqOetf(gL);
103 const float bp = pqOetf(bL);
104 // BT.2020 RGB' -> YUV'.
105 Y = kKr * rp + kKg * gp + kKb * bp;
106 U = (bp - Y) * kPbDiv;
107 V = (rp - Y) * kPrDiv;
108 };
109
110 float Y00, U00, V00;
111 float Y01, U01, V01;
112 float Y10, U10, V10;
113 float Y11, U11, V11;
114 loadPq(row0 + x * 4, Y00, U00, V00);
115 loadPq(row0 + x1 * 4, Y01, U01, V01);
116 loadPq(row1 + x * 4, Y10, U10, V10);
117 loadPq(row1 + x1 * 4, Y11, U11, V11);
118
119 // Y: per-pixel, limited-range 10-bit.
120 yr0[x] = clamp10(Y00 * 876.0f + 64.0f);
121 yr0[x1] = clamp10(Y01 * 876.0f + 64.0f);
122 yr1[x] = clamp10(Y10 * 876.0f + 64.0f);
123 yr1[x1] = clamp10(Y11 * 876.0f + 64.0f);
124
125 // UV: 4:2:0 average of 2x2 block.
126 const float Uavg = 0.25f * (U00 + U01 + U10 + U11);
127 const float Vavg = 0.25f * (V00 + V01 + V10 + V11);
128 ur[x / 2] = clamp10(Uavg * 896.0f + 512.0f);
129 vr[x / 2] = clamp10(Vavg * 896.0f + 512.0f);
130 }
131 }
132}
constexpr float kSdrRefFraction
Definition mxwrite.cpp:34

◆ is_valid_x264_preset()

bool anonymous_namespace{mxwrite.cpp}::is_valid_x264_preset ( const std::string & p)

Definition at line 455 of file mxwrite.cpp.

455 {
456 static const char *presets[] = {
457 "ultrafast","superfast","veryfast","faster","fast",
458 "medium","slow","slower","veryslow","placebo"
459 };
460 for (const char *n : presets) if (p == n) return true;
461 return false;
462}

◆ lowercase_ascii()

std::string anonymous_namespace{mxwrite.cpp}::lowercase_ascii ( std::string text)

Definition at line 464 of file mxwrite.cpp.

464 {
465 std::transform(text.begin(), text.end(), text.begin(), [](unsigned char ch) {
466 return static_cast<char>(std::tolower(ch));
467 });
468 return text;
469}

◆ pqOetf()

float anonymous_namespace{mxwrite.cpp}::pqOetf ( float L)
inline

Definition at line 42 of file mxwrite.cpp.

42 {
43 // L in [0,1] where 1.0 == 10000 nits; returns PQ code value in [0,1].
44 const float Lm = std::pow(std::max(0.0f, L), kPqM1);
45 const float num = kPqC1 + kPqC2 * Lm;
46 const float den = 1.0f + kPqC3 * Lm;
47 return std::pow(num / den, kPqM2);
48}

◆ srgbEotf()

float anonymous_namespace{mxwrite.cpp}::srgbEotf ( float v)
inline

Definition at line 36 of file mxwrite.cpp.

36 {
37 // sRGB non-linear -> linear light.
38 return (v <= 0.04045f) ? (v / 12.92f)
39 : std::pow((v + 0.055f) / 1.055f, 2.4f);
40}

◆ x264_preset_to_nvenc()

const char * anonymous_namespace{mxwrite.cpp}::x264_preset_to_nvenc ( const std::string & p)

Definition at line 443 of file mxwrite.cpp.

443 {
444 if (p == "ultrafast") return "p1";
445 if (p == "superfast") return "p2";
446 if (p == "veryfast" || p == "faster") return "p3";
447 if (p == "fast") return "p4";
448 if (p == "medium" || p.empty()) return "p5";
449 if (p == "slow" || p == "slower") return "p6";
450 if (p == "veryslow") return "p7";
451 // Allow passing NVENC preset names through directly.
452 return p.c_str();
453}

Variable Documentation

◆ kPqC1

float anonymous_namespace{mxwrite.cpp}::kPqC1 = 3424.0f / 4096.0f
constexpr

Definition at line 30 of file mxwrite.cpp.

◆ kPqC2

float anonymous_namespace{mxwrite.cpp}::kPqC2 = (2413.0f / 4096.0f) * 32.0f
constexpr

Definition at line 31 of file mxwrite.cpp.

◆ kPqC3

float anonymous_namespace{mxwrite.cpp}::kPqC3 = (2392.0f / 4096.0f) * 32.0f
constexpr

Definition at line 32 of file mxwrite.cpp.

◆ kPqM1

float anonymous_namespace{mxwrite.cpp}::kPqM1 = 2610.0f / 16384.0f
constexpr

Definition at line 28 of file mxwrite.cpp.

◆ kPqM2

float anonymous_namespace{mxwrite.cpp}::kPqM2 = (2523.0f / 4096.0f) * 128.0f
constexpr

Definition at line 29 of file mxwrite.cpp.

◆ kSdrRefFraction

float anonymous_namespace{mxwrite.cpp}::kSdrRefFraction = 100.0f / 10000.0f
constexpr

Definition at line 34 of file mxwrite.cpp.