2#include <Gfx/Graph/decoders/GPUVideoDecoder.hpp>
3#include <Gfx/Graph/decoders/ColorSpace.hpp>
5#include <libavformat/avformat.h>
12 static const constexpr auto rgb_filter = R
"_(#version 450
14)_" SCORE_GFX_VIDEO_UNIFORMS R"_(
16 layout(binding=3) uniform sampler2D y_tex;
18 layout(location = 0) in vec2 v_texcoord;
19 layout(location = 0) out vec4 fragColor;
21 vec4 processTexture(vec4 tex) {
29 fragColor = processTexture(texture(y_tex, v_texcoord));
34 QString f =
"",
bool invertY =
false,
bool nearest =
false)
36 , bytes_per_pixel{bytes_per_pixel}
38 , filter{std::move(f)}
43 QRhiTexture::Format format;
44 int bytes_per_pixel{};
54 auto& rhi = *r.
state.rhi;
55 const auto w = decoder.width, h = decoder.height;
59 auto tex = rhi.newTexture(format, QSize{w, h}, 1, QRhiTexture::Flag{});
63 auto sampler = rhi.newSampler(
66 QRhiSampler::None, QRhiSampler::ClampToEdge, QRhiSampler::ClampToEdge);
70 samplers.push_back({sampler, tex});
74 r.
state, vertexShader(invertY), QString(rgb_filter).arg(filter));
77 void exec(
RenderList&, QRhiResourceUpdateBatch& res, AVFrame& frame)
override
80 setPixels(res, frame.data[0], frame.linesize[0]);
84 setPixels(QRhiResourceUpdateBatch& res, uint8_t* pixels,
int stride)
const noexcept
86 const auto w = decoder.width, h = decoder.height;
87 auto y_tex = samplers[0].texture;
89 QRhiTextureUploadEntry entry{
92 QRhiTextureUploadDescription desc{entry};
93 res.uploadTexture(y_tex, desc);
99 static const constexpr auto rgb_filter = R
"_(#version 450
101)_" SCORE_GFX_VIDEO_UNIFORMS R"_(
104 layout(location = 0) in vec2 v_texcoord;
105 layout(location = 0) out vec4 fragColor;
107 vec4 processTexture(vec4 tex) {
108 vec4 processed = tex;
117 fragColor = processTexture(tex);
121 QRhiTexture::Format fmt, int bytes_per_pixel, QString planes,
124 , bytes_per_pixel{bytes_per_pixel}
127 , filter{std::move(f)}
130 QRhiTexture::Format format;
131 int bytes_per_pixel{};
138 auto& rhi = *r.
state.rhi;
139 const auto w = decoder.width, h = decoder.height;
141 QString samplers_code;
142 QString read_texture_code;
144 const int binding_orig = 3;
145 for(
int i = 0; i < planes.size(); i++)
147 samplers_code += QString(
" layout(binding=%1) uniform sampler2D t%2;\n")
148 .arg(binding_orig + i)
151 += QString(
" tex.%1 = texture(t%2, v_texcoord).r;\n")
156 auto tex = rhi.newTexture(format, QSize{w, h}, 1, QRhiTexture::Flag{});
160 auto sampler = rhi.newSampler(
161 QRhiSampler::Linear, QRhiSampler::Linear, QRhiSampler::None,
162 QRhiSampler::ClampToEdge, QRhiSampler::ClampToEdge);
166 samplers.push_back({sampler, tex});
170 r.
state, vertexShader(),
171 QString(rgb_filter).arg(samplers_code).arg(filter).arg(read_texture_code));
177 for(
int i = 0; i < planes.size(); i++)
179 setPixels(res, samplers[i].texture, frame.data[i], frame.linesize[i]);
184 QRhiResourceUpdateBatch& res, QRhiTexture* tex, uint8_t* pixels,
185 int stride)
const noexcept
187 const auto w = decoder.width, h = decoder.height;
189 QRhiTextureUploadEntry entry{
192 QRhiTextureUploadDescription desc{entry};
193 res.uploadTexture(tex, desc);
199 static const constexpr auto rgb_filter = R
"_(#version 450
201)_" SCORE_GFX_VIDEO_UNIFORMS R"_(
203 layout(binding=3) uniform sampler2DRect y_tex;
205 layout(location = 0) in vec2 v_texcoord;
206 layout(location = 0) out vec4 fragColor;
208 vec4 processTexture(vec4 tex) {
209 vec4 processed = tex;
216 fragColor = processTexture(texture(y_tex, v_texcoord));
219 static constexpr const char* vertex = R
"_(#version 450
220layout(location = 0) in vec2 position;
221layout(location = 1) in vec2 texcoord;
223layout(location = 0) out vec2 v_texcoord;
225)_" SCORE_GFX_VIDEO_UNIFORMS R"_(
227out gl_PerVertex { vec4 gl_Position; };
231 v_texcoord = texcoord * mat.texSz.xy;
232 gl_Position = renderer.clipSpaceCorrMatrix * vec4(position.x * mat.scale.x, position.y * mat.scale.y, 0.0, 1.);
233#if defined(QSHADER_HLSL) || defined(QSHADER_MSL)
234 gl_Position.y = - gl_Position.y;
243 , bytes_per_pixel{bytes_per_pixel}
245 , filter{std::move(f)}
248 QRhiTexture::Format format;
249 int bytes_per_pixel{};
255 auto& rhi = *r.
state.rhi;
256 const auto w = decoder.width, h = decoder.height;
260 auto tex = rhi.newTexture(format, QSize{w, h}, 1, QRhiTexture::Flag{});
264 auto sampler = rhi.newSampler(
265 QRhiSampler::Linear, QRhiSampler::Linear, QRhiSampler::None,
266 QRhiSampler::ClampToEdge, QRhiSampler::ClampToEdge);
270 samplers.push_back({sampler, tex});
279 setPixels(res, frame.data[0], frame.linesize[0]);
283 setPixels(QRhiResourceUpdateBatch& res, uint8_t* pixels,
int stride)
const noexcept
285 const auto w = decoder.width, h = decoder.height;
286 auto y_tex = samplers[0].texture;
288 QRhiTextureUploadEntry entry{
291 QRhiTextureUploadDescription desc{entry};
292 res.uploadTexture(y_tex, desc);
298 static const constexpr auto rgb_filter = R
"_(#version 450
300)_" SCORE_GFX_VIDEO_UNIFORMS R"_(
302 layout(binding=3) uniform sampler2D y_tex;
304 layout(location = 0) in vec2 v_texcoord;
305 layout(location = 0) out vec4 fragColor;
307 vec4 processTexture(vec4 tex) {
308 vec4 processed = tex;
315 float w = mat.texSz.x;
316 float h = mat.texSz.y;
317 int x = int(floor(v_texcoord.x * w) * 3.);
318 int y = int(v_texcoord.y * h);
319 float r = texelFetch(y_tex, ivec2(x + 0, y), 0).r;
320 float g = texelFetch(y_tex, ivec2(x + 1, y), 0).r;
321 float b = texelFetch(y_tex, ivec2(x + 2, y), 0).r;
322 fragColor = processTexture(vec4(r, g, b, 1.));
328 , filter{std::move(f)}
331 int bytes_per_pixel{};
337 auto& rhi = *r.
state.rhi;
338 const auto w = decoder.width, h = decoder.height;
344 auto tex = rhi.newTexture(QRhiTexture::R8, QSize{w * 3, h}, 1);
348 auto sampler = rhi.newSampler(
349 QRhiSampler::Nearest, QRhiSampler::Nearest, QRhiSampler::None,
350 QRhiSampler::ClampToEdge, QRhiSampler::ClampToEdge);
354 samplers.push_back({sampler, tex});
358 r.
state, vertexShader(), QString(rgb_filter).arg(filter));
364 setPixels(res, frame.data[0], frame.linesize[0]);
368 setPixels(QRhiResourceUpdateBatch& res, uint8_t* pixels,
int stride)
const noexcept
370 const auto w = decoder.width, h = decoder.height;
371 auto y_tex = samplers[0].texture;
373 QRhiTextureUploadEntry entry{
376 QRhiTextureUploadDescription desc{entry};
377 res.uploadTexture(y_tex, desc);
383 static const constexpr auto rgb_filter = R
"_(#version 450
385)_" SCORE_GFX_VIDEO_UNIFORMS R"_(
387 layout(binding=3) uniform sampler2D y_tex;
389 layout(location = 0) in vec2 v_texcoord;
390 layout(location = 0) out vec4 fragColor;
392 vec4 processTexture(vec4 tex) {
393 vec4 processed = tex;
400 float w = mat.texSz.x;
401 float h = mat.texSz.y;
402 int x = int(floor(v_texcoord.x * w) * 3.);
403 int y = int(v_texcoord.y * h);
404 const float s = )_" SCORE_GFX_MSB_ALIGNED_SCALE R"_(;
405 float r = texelFetch(y_tex, ivec2(x + 0, y), 0).r * s;
406 float g = texelFetch(y_tex, ivec2(x + 1, y), 0).r * s;
407 float b = texelFetch(y_tex, ivec2(x + 2, y), 0).r * s;
408 fragColor = processTexture(vec4(r, g, b, 1.));
413 , filter{std::move(f)}
421 auto& rhi = *r.
state.rhi;
422 const auto w = decoder.width, h = decoder.height;
425 auto tex = rhi.newTexture(QRhiTexture::R16, QSize{w * 3, h}, 1, QRhiTexture::Flag{});
428 auto sampler = rhi.newSampler(
429 QRhiSampler::Nearest, QRhiSampler::Nearest, QRhiSampler::None,
430 QRhiSampler::ClampToEdge, QRhiSampler::ClampToEdge);
433 samplers.push_back({sampler, tex});
437 r.
state, vertexShader(), QString(rgb_filter).arg(filter));
442 const auto w = decoder.width, h = decoder.height;
443 auto y_tex = samplers[0].texture;
446 QRhiTextureUploadEntry entry{
449 QRhiTextureUploadDescription desc{entry};
450 res.uploadTexture(y_tex, desc);
460 static const constexpr auto rgb_filter = R
"_(#version 450
462)_" SCORE_GFX_VIDEO_UNIFORMS R"_(
464 layout(binding=3) uniform sampler2D y_tex;
466 layout(location = 0) in vec2 v_texcoord;
467 layout(location = 0) out vec4 fragColor;
469 vec4 processTexture(vec4 tex) {
470 vec4 processed = tex;
477 float w = mat.texSz.x;
478 float h = mat.texSz.y;
479 int x = int(floor(v_texcoord.x * w) * 4.);
480 int y = int(v_texcoord.y * h);
481 const float s = )_" SCORE_GFX_MSB_ALIGNED_SCALE R"_(;
482 float r = texelFetch(y_tex, ivec2(x + 0, y), 0).r * s;
483 float g = texelFetch(y_tex, ivec2(x + 1, y), 0).r * s;
484 float b = texelFetch(y_tex, ivec2(x + 2, y), 0).r * s;
485 float a = texelFetch(y_tex, ivec2(x + 3, y), 0).r * s;
486 fragColor = processTexture(vec4(r, g, b, a));
491 , filter{std::move(f)}
499 auto& rhi = *r.
state.rhi;
500 const auto w = decoder.width, h = decoder.height;
503 auto tex = rhi.newTexture(QRhiTexture::R16, QSize{w * 4, h}, 1, QRhiTexture::Flag{});
506 auto sampler = rhi.newSampler(
507 QRhiSampler::Nearest, QRhiSampler::Nearest, QRhiSampler::None,
508 QRhiSampler::ClampToEdge, QRhiSampler::ClampToEdge);
511 samplers.push_back({sampler, tex});
515 r.
state, vertexShader(), QString(rgb_filter).arg(filter));
520 const auto w = decoder.width, h = decoder.height;
521 auto y_tex = samplers[0].texture;
524 QRhiTextureUploadEntry entry{
527 QRhiTextureUploadDescription desc{entry};
528 res.uploadTexture(y_tex, desc);
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
bool nearestSampling
Definition RGBA.hpp:48
std::pair< QShader, QShader > init(RenderList &r) override
Initialize a GPUVideoDecoder.
Definition RGBA.hpp:52
void exec(RenderList &, QRhiResourceUpdateBatch &res, AVFrame &frame) override
Decode and upload a video frame to the GPU.
Definition RGBA.hpp:77
void exec(RenderList &, QRhiResourceUpdateBatch &res, AVFrame &frame) override
Decode and upload a video frame to the GPU.
Definition RGBA.hpp:276
std::pair< QShader, QShader > init(RenderList &r) override
Initialize a GPUVideoDecoder.
Definition RGBA.hpp:253
void exec(RenderList &, QRhiResourceUpdateBatch &res, AVFrame &frame) override
Decode and upload a video frame to the GPU.
Definition RGBA.hpp:174
std::pair< QShader, QShader > init(RenderList &r) override
Initialize a GPUVideoDecoder.
Definition RGBA.hpp:136
void exec(RenderList &, QRhiResourceUpdateBatch &res, AVFrame &frame) override
Decode and upload a video frame to the GPU.
Definition RGBA.hpp:361
std::pair< QShader, QShader > init(RenderList &r) override
Initialize a GPUVideoDecoder.
Definition RGBA.hpp:335
std::pair< QShader, QShader > init(RenderList &r) override
Initialize a GPUVideoDecoder.
Definition RGBA.hpp:419
void exec(RenderList &, QRhiResourceUpdateBatch &res, AVFrame &frame) override
Decode and upload a video frame to the GPU.
Definition RGBA.hpp:440
void exec(RenderList &, QRhiResourceUpdateBatch &res, AVFrame &frame) override
Decode and upload a video frame to the GPU.
Definition RGBA.hpp:518
std::pair< QShader, QShader > init(RenderList &r) override
Initialize a GPUVideoDecoder.
Definition RGBA.hpp:497