Loading...
Searching...
No Matches
YUYV422.hpp
1#pragma once
2#include <Gfx/Graph/decoders/ColorSpace.hpp>
3#include <Gfx/Graph/decoders/GPUVideoDecoder.hpp>
4extern "C" {
5#include <libavformat/avformat.h>
6}
7
8namespace score::gfx
9{
16{
17 static const constexpr auto frag = R"_(#version 450
18
19)_" SCORE_GFX_VIDEO_UNIFORMS R"_(
20
21layout(binding=3) uniform sampler2D u_tex;
22
23layout(location = 0) in vec2 v_texcoord;
24layout(location = 0) out vec4 fragColor;
25
26%2
27
28vec4 processTexture(vec4 tex) {
29 vec4 processed = convert_to_rgb(tex);
30 { %1 }
31 return processed;
32}
33
34void main() {
35 // YUYV packs Y0 U Y1 V into RGBA as x=Y0 y=U z=Y1 w=V
36 // Input texture is half the width of the output (one RGBA texel = 2 pixels)
37 float colIndex = floor(v_texcoord.x * mat.texSz.x);
38 float oddCol = mod(colIndex, 2.0);
39
40 // Offset by half an input pixel to sample the correct texel center
41 vec2 dxInput = 0.5 * vec2(1.0 / mat.texSz.x, 0.0);
42
43 float oddY = texture(u_tex, v_texcoord - dxInput).z;
44 float evenY = texture(u_tex, v_texcoord + dxInput).x;
45 float y = mix(evenY, oddY, oddCol);
46
47 vec2 uv = texture(u_tex, v_texcoord).%3;
48
49 fragColor = processTexture(vec4(y, uv.x, uv.y, 1.));
50}
51)_";
52
54 explicit YUYV422Decoder(Video::ImageFormat& d, bool swapChroma = false)
55 : decoder{d}
56 , yvyu{swapChroma}
57 {
58 }
59
60 Video::ImageFormat& decoder;
61 bool yvyu{};
62 std::pair<QShader, QShader> init(RenderList& r) override
63 {
64 auto& rhi = *r.state.rhi;
65
66 const auto w = decoder.width, h = decoder.height;
67 // Y
68 {
69 auto tex = rhi.newTexture(QRhiTexture::RGBA8, {w / 2, h}, 1, QRhiTexture::Flag{});
70 tex->create();
71
72 auto sampler = rhi.newSampler(
73 QRhiSampler::Linear, QRhiSampler::Linear, QRhiSampler::None,
74 QRhiSampler::ClampToEdge, QRhiSampler::ClampToEdge);
75 sampler->create();
76 samplers.push_back({sampler, tex});
77 }
78
80 r.state, vertexShader(),
81 QString(frag).arg("").arg(colorMatrix(decoder)).arg(yvyu ? "wy" : "yw"));
82 }
83
84 void exec(RenderList&, QRhiResourceUpdateBatch& res, AVFrame& frame) override
85 {
86 setYPixels(res, frame.data[0], frame.linesize[0]);
87 }
88
89 void
90 setYPixels(QRhiResourceUpdateBatch& res, uint8_t* pixels, int stride) const noexcept
91 {
92 const auto w = decoder.width, h = decoder.height;
93 auto y_tex = samplers[0].texture;
94
95 // Texture is RGBA8 at {w/2, h}: 4 bytes per texel = one YUYV macropixel
96 QRhiTextureUploadEntry entry{0, 0, createTextureUpload(pixels, w / 2, h, 4, stride)};
97
98 QRhiTextureUploadDescription desc{entry};
99 res.uploadTexture(y_tex, desc);
100 }
101};
102
109{
110 static const constexpr auto frag = R"_(#version 450
111
112)_" SCORE_GFX_VIDEO_UNIFORMS R"_(
113
114layout(binding=3) uniform sampler2D u_tex;
115
116layout(location = 0) in vec2 v_texcoord;
117layout(location = 0) out vec4 fragColor;
118
119%2
120
121vec4 processTexture(vec4 tex) {
122 vec4 processed = convert_to_rgb(tex);
123 { %1 }
124 return processed;
125}
126
127void main() {
128 // UYVY packs U0 Y0 V0 Y1 into RGBA as x=U0 y=Y0 z=V0 w=Y1
129 // Input texture is half the width of the output (one RGBA texel = 2 pixels)
130 float colIndex = floor(v_texcoord.x * mat.texSz.x);
131 float oddCol = mod(colIndex, 2.0);
132
133 // Offset by half an input pixel to sample the correct texel center
134 vec2 dxInput = 0.5 * vec2(1.0 / mat.texSz.x, 0.0);
135
136 float oddY = texture(u_tex, v_texcoord - dxInput).w;
137 float evenY = texture(u_tex, v_texcoord + dxInput).y;
138 float y = mix(evenY, oddY, oddCol);
139
140 vec2 uv = texture(u_tex, v_texcoord).%3;
141
142 fragColor = processTexture(vec4(y, uv.x, uv.y, 1.));
143}
144)_";
145
147 UYVY422Decoder(Video::ImageFormat& d, bool swapChroma = false)
148 : decoder{d}
149 , vyuy{swapChroma}
150 {
151 }
152
153 Video::ImageFormat& decoder;
154 bool vyuy{};
155 std::pair<QShader, QShader> init(RenderList& r) override
156 {
157 auto& rhi = *r.state.rhi;
158
159 const auto w = decoder.width, h = decoder.height;
160 // Y
161 {
162 auto tex = rhi.newTexture(QRhiTexture::RGBA8, {w / 2, h}, 1, QRhiTexture::Flag{});
163 tex->create();
164
165 auto sampler = rhi.newSampler(
166 QRhiSampler::Linear, QRhiSampler::Linear, QRhiSampler::None,
167 QRhiSampler::ClampToEdge, QRhiSampler::ClampToEdge);
168 sampler->create();
169 samplers.push_back({sampler, tex});
170 }
171
173 r.state, vertexShader(),
174 QString(frag).arg("").arg(colorMatrix(decoder)).arg(vyuy ? "zx" : "xz"));
175 }
176
177 void exec(RenderList&, QRhiResourceUpdateBatch& res, AVFrame& frame) override
178 {
179 auto y_tex = samplers[0].texture;
180
181 auto pixels = frame.data[0];
182 auto stride = frame.linesize[0];
183 // Texture is RGBA8 at {w/2, h}: 4 bytes per texel = one UYVY macropixel
184 QRhiTextureUploadEntry entry{
185 0, 0, createTextureUpload(pixels, frame.width / 2, frame.height, 4, stride)};
186
187 QRhiTextureUploadDescription desc{entry};
188 res.uploadTexture(y_tex, desc);
189 }
190};
191
192}
Processes and renders a video frame on the GPU.
Definition GPUVideoDecoder.hpp:90
static QRhiTextureSubresourceUploadDescription createTextureUpload(uint8_t *pixels, int w, int h, int bytesPerPixel, int stride)
Utility method to create a QRhiTextureSubresourceUploadDescription.
Definition GPUVideoDecoder.cpp:22
List of nodes to be rendered to an output.
Definition RenderList.hpp:30
RenderState & state
RenderState corresponding to this RenderList.
Definition RenderList.hpp:169
Graphics rendering pipeline for ossia score.
Definition Filter/PreviewWidget.hpp:11
std::pair< QShader, QShader > makeShaders(const RenderState &v, QString vert, QString frag, int multiViewCount)
Get a pair of compiled vertex / fragment shaders from GLSL 4.5 sources.
Definition score-plugin-gfx/Gfx/Graph/Utils.cpp:1238
Definition VideoInterface.hpp:26
Decodes UYVY422 video, mostly used for NDI.
Definition YUYV422.hpp:109
void exec(RenderList &, QRhiResourceUpdateBatch &res, AVFrame &frame) override
Decode and upload a video frame to the GPU.
Definition YUYV422.hpp:177
UYVY422Decoder(Video::ImageFormat &d, bool swapChroma=false)
VYUY is UYVY with the two chroma taps exchanged.
Definition YUYV422.hpp:147
std::pair< QShader, QShader > init(RenderList &r) override
Initialize a GPUVideoDecoder.
Definition YUYV422.hpp:155
Decodes YUYV422 video.
Definition YUYV422.hpp:16
YUYV422Decoder(Video::ImageFormat &d, bool swapChroma=false)
YVYU is YUYV with the two chroma taps exchanged; nothing else differs.
Definition YUYV422.hpp:54
std::pair< QShader, QShader > init(RenderList &r) override
Initialize a GPUVideoDecoder.
Definition YUYV422.hpp:62
void exec(RenderList &, QRhiResourceUpdateBatch &res, AVFrame &frame) override
Decode and upload a video frame to the GPU.
Definition YUYV422.hpp:84