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