Loading...
Searching...
No Matches
WireDecoderFactory.hpp
Go to the documentation of this file.
1#pragma once
2
18#include <Gfx/Graph/decoders/Bayer.hpp>
19#include <Gfx/Graph/decoders/NV12.hpp>
22#include <Gfx/Graph/decoders/NV16.hpp>
23#include <Gfx/Graph/decoders/NV24.hpp>
24#include <Gfx/Graph/decoders/P010.hpp>
25#include <Gfx/Graph/decoders/R210.hpp>
26#include <Gfx/Graph/decoders/RGBA.hpp>
27#include <Gfx/Graph/decoders/VUYA.hpp>
28#include <Gfx/Graph/decoders/YUV420.hpp>
29#include <Gfx/Graph/decoders/YUV422.hpp>
30#include <Gfx/Graph/decoders/V210.hpp>
31#include <Gfx/Graph/decoders/YUV422P10.hpp>
32#include <Gfx/Graph/decoders/YUV444.hpp>
33#include <Gfx/Graph/decoders/YUV444P12.hpp>
34#include <Gfx/Graph/decoders/YUV444P10.hpp>
35#include <Gfx/Graph/decoders/YUV422P12.hpp>
36#include <Gfx/Graph/decoders/YUV420P10.hpp>
37#include <Gfx/Graph/decoders/P210.hpp>
38#include <Gfx/Graph/decoders/PA16.hpp>
39#include <Gfx/Graph/decoders/UYVA.hpp>
40#include <Gfx/Graph/decoders/YUYV422.hpp>
42
43#include <Video/VideoInterface.hpp>
44
45#include <memory>
46
47namespace score::gfx
48{
49
50inline std::unique_ptr<GPUVideoDecoder>
51makeWireDecoder(Video::VideoPixelFormat fmt, Video::ImageFormat& d)
52{
54 switch(fmt)
55 {
56 // -- packed 8-bit YUV 4:2:2 --
57 case F::UYVY422:
58 return std::make_unique<UYVY422Decoder>(d);
59 case F::YUYV422:
60 return std::make_unique<YUYV422Decoder>(d);
61 // Chroma-swapped twins: same unpack, the two UV taps exchanged.
62 case F::YVYU422:
63 return std::make_unique<YUYV422Decoder>(d, /*swapChroma=*/true);
64 case F::VYUY422:
65 return std::make_unique<UYVY422Decoder>(d, /*swapChroma=*/true);
66
67 // -- packed 10-bit YUV 4:2:2 --
68 case F::V210:
69 return std::make_unique<V210Decoder>(d);
70
71 // -- packed 8-bit RGB (the input texture stores these byte orders) --
72 case F::BGRA8: // memory [B,G,R,A]
73 return std::make_unique<PackedDecoder>(QRhiTexture::BGRA8, 4, d);
74 case F::RGBA8: // memory [R,G,B,A]
75 return std::make_unique<PackedDecoder>(QRhiTexture::RGBA8, 4, d);
76 // The remaining 32-bit orderings are the same bytes read differently.
77 // QRhiTexture::BGRA8 describes the UPLOAD byte order -- the sampler still
78 // yields .r == red -- so a texture whose memory is B,G,R,A needs no
79 // swizzle, and the others below are expressed relative to that. The X
80 // variants additionally pin alpha, whose byte is padding and would
81 // otherwise sample as transparent.
82 case F::BGRX8:
83 return std::make_unique<PackedDecoder>(
84 QRhiTexture::BGRA8, 4, d, "processed.rgba = vec4(tex.rgb, 1.0);");
85 case F::RGBX8:
86 return std::make_unique<PackedDecoder>(
87 QRhiTexture::RGBA8, 4, d, "processed.rgba = vec4(tex.rgb, 1.0);");
88 case F::ARGB8: // memory [A,R,G,B]
89 return std::make_unique<PackedDecoder>(
90 QRhiTexture::RGBA8, 4, d, "processed.rgba = vec4(tex.gba, tex.r);");
91 case F::XRGB8:
92 return std::make_unique<PackedDecoder>(
93 QRhiTexture::RGBA8, 4, d, "processed.rgba = vec4(tex.gba, 1.0);");
94 case F::ABGR8: // memory [A,B,G,R]
95 return std::make_unique<PackedDecoder>(
96 QRhiTexture::RGBA8, 4, d, "processed.rgba = vec4(tex.abg, tex.r);");
97 case F::XBGR8:
98 return std::make_unique<PackedDecoder>(
99 QRhiTexture::RGBA8, 4, d, "processed.rgba = vec4(tex.abg, 1.0);");
100
101 // -- single-channel / greyscale --
102 // Machine-vision and depth sensors deliver one channel per pixel: V4L2
103 // GREY, RealSense Z16, industrial Mono8/10/12/16. Same texture formats and
104 // swizzle GPUVideoDecoderFactory already uses for AV_PIX_FMT_GRAY8/GRAY16 --
105 // this factory maps the neutral WIRE enum rather than AVPixelFormat, so the
106 // case is needed here too, but the decoder behind it is the shared one.
107 // 10- and 12-bit mono travel in a 16-bit container and share the R16 path.
108 case F::Mono8:
109 return std::make_unique<PackedDecoder>(
110 QRhiTexture::R8, 1, d,
111 "processed.rgba = vec4(tex.r, tex.r, tex.r, 1.0);");
112 // 10- and 12-bit mono ride in a 16-bit lane, so the sampler normalises
113 // against 65535 and the image comes out 64x / 16x too dark. Scale back to
114 // full range; Mono16 already fills the lane.
115 case F::Mono10:
116 return std::make_unique<PackedDecoder>(
117 QRhiTexture::R16, 2, d,
118 "processed.rgba = vec4(vec3(tex.r * 64.0625), 1.0);");
119 case F::Mono12:
120 return std::make_unique<PackedDecoder>(
121 QRhiTexture::R16, 2, d,
122 "processed.rgba = vec4(vec3(tex.r * 16.0039), 1.0);");
123 case F::Mono16:
124 return std::make_unique<PackedDecoder>(
125 QRhiTexture::R16, 2, d,
126 "processed.rgba = vec4(tex.r, tex.r, tex.r, 1.0);");
127 // -- Bayer: one sample per pixel, demosaiced on the GPU ---------------
128 // The CFA order travels with the format, so it is passed to the decoder
129 // rather than assumed. The 10- and 12-bit orders ride right-aligned in a
130 // 16-bit lane, so they carry the same rescale as Mono10 / Mono12.
131 case F::BayerRGGB8:
132 case F::BayerRG8: // PFNC spelling of the same order
133 return std::make_unique<BayerDecoder>(
134 QRhiTexture::R8, 1, d, BayerDecoder::Phase::RGGB);
135 case F::BayerBGGR8:
136 return std::make_unique<BayerDecoder>(
137 QRhiTexture::R8, 1, d, BayerDecoder::Phase::BGGR);
138 case F::BayerGRBG8:
139 return std::make_unique<BayerDecoder>(
140 QRhiTexture::R8, 1, d, BayerDecoder::Phase::GRBG);
141 case F::BayerGBRG8:
142 return std::make_unique<BayerDecoder>(
143 QRhiTexture::R8, 1, d, BayerDecoder::Phase::GBRG);
144 case F::BayerRGGB16:
145 return std::make_unique<BayerDecoder>(
146 QRhiTexture::R16, 2, d, BayerDecoder::Phase::RGGB);
147 case F::BayerBGGR16:
148 return std::make_unique<BayerDecoder>(
149 QRhiTexture::R16, 2, d, BayerDecoder::Phase::BGGR);
150 case F::BayerRGGB10:
151 return std::make_unique<BayerDecoder>(
152 QRhiTexture::R16, 2, d, BayerDecoder::Phase::RGGB, 64.0625);
153 case F::BayerBGGR10:
154 return std::make_unique<BayerDecoder>(
155 QRhiTexture::R16, 2, d, BayerDecoder::Phase::BGGR, 64.0625);
156 case F::BayerGRBG10:
157 return std::make_unique<BayerDecoder>(
158 QRhiTexture::R16, 2, d, BayerDecoder::Phase::GRBG, 64.0625);
159 case F::BayerGBRG10:
160 return std::make_unique<BayerDecoder>(
161 QRhiTexture::R16, 2, d, BayerDecoder::Phase::GBRG, 64.0625);
162 case F::BayerRG12:
163 return std::make_unique<BayerDecoder>(
164 QRhiTexture::R16, 2, d, BayerDecoder::Phase::RGGB, 16.0039);
165
166 // Big-endian: sample the two bytes separately and reassemble, since R16
167 // would read them in the host's order.
168 case F::Mono16BE:
169 return std::make_unique<PackedDecoder>(
170 QRhiTexture::RG8, 2, d,
171 "float be = (tex.r * 255.0 * 256.0 + tex.g * 255.0) / 65535.0;"
172 "processed.rgba = vec4(be, be, be, 1.0);",
173 /*invertY=*/false, /*nearest=*/true);
174
175 // -- sub-byte packed RGB ---------------------------------------------
176 // One parameterised unpacker; each format is just its bit layout. Bit
177 // offsets are LSB-relative in the reassembled container, matching how
178 // V4L2 documents them.
179 case F::RGB332: // one byte: RRRGGGBB
181 {.containerBytes = 1, .bigEndian = false,
182 .r = {5, 3}, .g = {2, 3}, .b = {0, 2}, .a = {0, 0}}, d);
183 case F::RGB565:
185 {.containerBytes = 2, .bigEndian = false,
186 .r = {11, 5}, .g = {5, 6}, .b = {0, 5}, .a = {0, 0}}, d);
187 case F::RGB565BE:
189 {.containerBytes = 2, .bigEndian = true,
190 .r = {11, 5}, .g = {5, 6}, .b = {0, 5}, .a = {0, 0}}, d);
191 case F::RGB555:
193 {.containerBytes = 2, .bigEndian = false,
194 .r = {10, 5}, .g = {5, 5}, .b = {0, 5}, .a = {0, 0}}, d);
195 case F::RGB555BE:
197 {.containerBytes = 2, .bigEndian = true,
198 .r = {10, 5}, .g = {5, 5}, .b = {0, 5}, .a = {0, 0}}, d);
199 case F::ARGB1555:
201 {.containerBytes = 2, .bigEndian = false,
202 .r = {10, 5}, .g = {5, 5}, .b = {0, 5}, .a = {15, 1}}, d);
203 case F::RGB444:
205 {.containerBytes = 2, .bigEndian = false,
206 .r = {8, 4}, .g = {4, 4}, .b = {0, 4}, .a = {0, 0}}, d);
207 case F::ARGB4444:
209 {.containerBytes = 2, .bigEndian = false,
210 .r = {8, 4}, .g = {4, 4}, .b = {0, 4}, .a = {12, 4}}, d);
211
212 // Same containers as the RGB bitfields above, carrying Y/U/V. V4L2
213 // documents them as "A/XYUV": alpha high, then Y, U, V downwards.
214 // The high bits are NOT alpha: V4L2 documents them as "undefined when
215 // reading from the driver" for the sub-8bpc packed YUV formats, unlike the
216 // 8bpc AYUV32/VUYA32 family whose alpha is meaningful. They are ignored;
217 // consuming them makes the frame fully transparent on any driver that
218 // leaves them zero.
219 case F::AYUV4444:
220 return std::make_unique<PackedBitfieldYUVDecoder>(
221 d, PackedBitfieldYUVLayout{
222 .y = {8, 4}, .u = {4, 4}, .v = {0, 4}, .a = {0, 0}});
223 case F::AYUV1555:
224 return std::make_unique<PackedBitfieldYUVDecoder>(
225 d, PackedBitfieldYUVLayout{
226 .y = {10, 5}, .u = {5, 5}, .v = {0, 5}, .a = {0, 0}});
227 case F::YUV565:
228 return std::make_unique<PackedBitfieldYUVDecoder>(
229 d, PackedBitfieldYUVLayout{
230 .y = {11, 5}, .u = {5, 6}, .v = {0, 5}, .a = {0, 0}});
231
232 // -- packed 10-bit RGB (r210, DeckLink SDI 4:4:4 wire) --
233 case F::R210:
234 return std::make_unique<R210Decoder>(d);
235
236 // -- packed RGB 24/48-bit --
237 case F::RGB24:
238 return std::make_unique<RGB24Decoder>(d);
239 case F::BGR24:
240 // Same unpacker, opposite byte order -- without the swizzle R and B come
241 // out exchanged. GPUVideoDecoderFactory passes the same filter for
242 // AV_PIX_FMT_BGR24.
243 return std::make_unique<RGB24Decoder>(
244 d, "processed.rgb = tex.bgr;");
245 case F::RGB48:
246 return std::make_unique<RGB48Decoder>(d);
247
248 // -- planar / semi-planar (capture cards that convert on-chip, e.g. Magewell) --
249 case F::NV12:
250 return std::make_unique<NV12Decoder>(d, /*inverted=*/false);
251 case F::NV21:
252 return std::make_unique<NV12Decoder>(d, /*inverted=*/true);
253 case F::NV16:
254 return std::make_unique<NV16Decoder>(d, /*swapChroma=*/false);
255 case F::NV61:
256 return std::make_unique<NV16Decoder>(d, /*swapChroma=*/true);
257 case F::NV24:
258 return std::make_unique<NV24Decoder>(d, /*inverted=*/false);
259 case F::NV42:
260 return std::make_unique<NV24Decoder>(d, /*inverted=*/true);
261 case F::VUYA:
262 return std::make_unique<VUYADecoder>(d, /*opaque=*/false);
263 case F::VUYX:
264 return std::make_unique<VUYADecoder>(d, /*opaque=*/true);
265 // Same 32 bits, different component order.
266 case F::AYUV:
267 return std::make_unique<VUYADecoder>(d, /*opaque=*/false, "gba", 'r');
268 case F::XYUV:
269 return std::make_unique<VUYADecoder>(d, /*opaque=*/true, "gba", 'r');
270 case F::YUVA:
271 return std::make_unique<VUYADecoder>(d, /*opaque=*/false, "rgb", 'a');
272 case F::YUVX:
273 return std::make_unique<VUYADecoder>(d, /*opaque=*/true, "rgb", 'a');
274 case F::YUV420P:
275 return std::make_unique<YUV420Decoder>(d, /*swapPlanes=*/false);
276 case F::YVU420P:
277 return std::make_unique<YUV420Decoder>(d, /*swapPlanes=*/true);
278 case F::YUV422P:
279 return std::make_unique<YUV422Decoder>(d);
280 case F::P010:
281 return std::make_unique<P010Decoder>(d);
282 case F::YUV422P10:
283 return std::make_unique<YUV422P10Decoder>(d);
284 // The remaining planar decoders, shared with the ffmpeg path.
285 case F::YUV422P12:
286 return std::make_unique<YUV422P12Decoder>(d);
287 case F::YUV420P10:
288 return std::make_unique<YUV420P10Decoder>(d);
289 case F::YUV444P:
290 return std::make_unique<YUV444Decoder>(d);
291 case F::YUV444P10:
292 return std::make_unique<YUV444P10Decoder>(d);
293 case F::YUV444P12:
294 return std::make_unique<YUV444P12Decoder>(d);
295 case F::P210:
296 return std::make_unique<P210Decoder>(d);
297 // P216 is P210's layout with sixteen significant bits rather than ten, and
298 // the same MSB-aligned scale.
299 case F::P216:
300 return std::make_unique<P210Decoder>(d);
301
302 // NDI's two alpha layouts: a picture followed by its own alpha plane.
303 case F::UYVA422A:
304 return std::make_unique<UYVADecoder>(d);
305 case F::PA16:
306 return std::make_unique<PA16Decoder>(d);
307
308 default:
309 return nullptr;
310 }
311}
312
313} // namespace score::gfx
Decoder for RGB packed into bit fields narrower than a byte.
YUV packed into sub-byte bit fields (V4L2 Y444 / YUVO / YUVP).
Vendor-neutral pixel format vocabulary + descriptive metadata.
VideoPixelFormat
Definition VideoPixelFormat.hpp:235
Graphics rendering pipeline for ossia score.
Definition Filter/PreviewWidget.hpp:11
std::unique_ptr< GPUVideoDecoder > makePackedBitfieldDecoder(const PackedBitfieldLayout &l, Video::ImageFormat &d)
Convenience: the decoder for a packed-bitfield format.
Definition PackedBitfield.hpp:87
Definition VideoInterface.hpp:29