YUV422P10.hpp
1 #pragma once
2 #include <Gfx/Graph/decoders/GPUVideoDecoder.hpp>
3 extern "C" {
4 #include <libavformat/avformat.h>
5 }
6 
7 namespace score::gfx
8 {
9 
18 {
19  static const constexpr auto yuv422_filter = R"_(#version 450
20 
21 )_" SCORE_GFX_VIDEO_UNIFORMS R"_(
22 
23 layout(binding=3) uniform sampler2D y_tex;
24 layout(binding=4) uniform sampler2D u_tex;
25 layout(binding=5) uniform sampler2D v_tex;
26 
27 layout(location = 0) in vec2 v_texcoord;
28 layout(location = 0) out vec4 fragColor;
29 
30 // See softpixel.com/~cwright/programming/colorspace/yuv
31 const vec3 offset = vec3(0., -0.5, -0.5);
32 const mat3 coeff = mat3(1.0 , 1.0 , 1.0,
33  0.0 , -0.3455, 1.7790,
34  1.4075, -0.7169, 0.);
35 void main()
36 {
37  float y = 64. * texture(y_tex, v_texcoord).r;
38  float u = 64. * texture(u_tex, v_texcoord).r;
39  float v = 64. * texture(v_tex, v_texcoord).r;
40 
41  fragColor = vec4(coeff * (vec3(y,u,v) + offset), 1);
42 }
43 )_";
44 
46  : decoder{d}
47  {
48  }
49 
50  Video::ImageFormat& decoder;
51  std::pair<QShader, QShader> init(RenderList& r) override
52  {
53  auto& rhi = *r.state.rhi;
54 
55  const auto w = decoder.width, h = decoder.height;
56  // Y
57  {
58  auto tex = rhi.newTexture(QRhiTexture::R16, {w, h}, 1, QRhiTexture::Flag{});
59  tex->create();
60 
61  auto sampler = rhi.newSampler(
62  QRhiSampler::Linear, QRhiSampler::Linear, QRhiSampler::None,
63  QRhiSampler::ClampToEdge, QRhiSampler::ClampToEdge);
64  sampler->create();
65  samplers.push_back({sampler, tex});
66  }
67 
68  // U
69  {
70  auto tex = rhi.newTexture(QRhiTexture::R16, {w / 2, h}, 1, QRhiTexture::Flag{});
71  tex->create();
72 
73  auto sampler = rhi.newSampler(
74  QRhiSampler::Linear, QRhiSampler::Linear, QRhiSampler::None,
75  QRhiSampler::ClampToEdge, QRhiSampler::ClampToEdge);
76  sampler->create();
77  samplers.push_back({sampler, tex});
78  }
79 
80  // V
81  {
82  auto tex = rhi.newTexture(QRhiTexture::R16, {w / 2, h}, 1, QRhiTexture::Flag{});
83  tex->create();
84 
85  auto sampler = rhi.newSampler(
86  QRhiSampler::Linear, QRhiSampler::Linear, QRhiSampler::None,
87  QRhiSampler::ClampToEdge, QRhiSampler::ClampToEdge);
88  sampler->create();
89  samplers.push_back({sampler, tex});
90  }
91 
92  return score::gfx::makeShaders(r.state, vertexShader(), yuv422_filter);
93  }
94 
95  void exec(RenderList&, QRhiResourceUpdateBatch& res, AVFrame& frame) override
96  {
97  setYPixels(res, frame.data[0], frame.linesize[0]);
98  setUPixels(res, frame.data[1], frame.linesize[1]);
99  setVPixels(res, frame.data[2], frame.linesize[2]);
100  }
101 
102  void
103  setYPixels(QRhiResourceUpdateBatch& res, uint8_t* pixels, int stride) const noexcept
104  {
105  const auto w = decoder.width, h = decoder.height;
106  auto y_tex = samplers[0].texture;
107 
108  QRhiTextureUploadEntry entry{0, 0, createTextureUpload(pixels, w, h, 2, stride)};
109 
110  QRhiTextureUploadDescription desc{entry};
111  res.uploadTexture(y_tex, desc);
112  }
113 
114  void
115  setUPixels(QRhiResourceUpdateBatch& res, uint8_t* pixels, int stride) const noexcept
116  {
117  const auto w = decoder.width / 2, h = decoder.height;
118  auto u_tex = samplers[1].texture;
119 
120  QRhiTextureUploadEntry entry{0, 0, createTextureUpload(pixels, w, h, 2, stride)};
121 
122  QRhiTextureUploadDescription desc{entry};
123 
124  res.uploadTexture(u_tex, desc);
125  }
126 
127  void
128  setVPixels(QRhiResourceUpdateBatch& res, uint8_t* pixels, int stride) const noexcept
129  {
130  const auto w = decoder.width / 2, h = decoder.height;
131  auto v_tex = samplers[2].texture;
132 
133  QRhiTextureUploadEntry entry{0, 0, createTextureUpload(pixels, w, h, 2, stride)};
134 
135  QRhiTextureUploadDescription desc{entry};
136  res.uploadTexture(v_tex, desc);
137  }
138 };
139 
140 }
Processes and renders a video frame on the GPU.
Definition: GPUVideoDecoder.hpp:43
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:19
RenderState & state
RenderState corresponding to this RenderList.
Definition: RenderList.hpp:89
Graphics rendering pipeline for ossia score.
Definition: Filter/PreviewWidget.hpp:12
std::pair< QShader, QShader > makeShaders(const RenderState &v, QString vert, QString frag)
Get a pair of compiled vertex / fragment shaders from GLSL 4.5 sources.
Definition: score-plugin-gfx/Gfx/Graph/Utils.cpp:342
Definition: VideoInterface.hpp:16
Decodes YUV422 videos.
Definition: YUV422P10.hpp:18
std::pair< QShader, QShader > init(RenderList &r) override
Initialize a GPUVideoDecoder.
Definition: YUV422P10.hpp:51
void exec(RenderList &, QRhiResourceUpdateBatch &res, AVFrame &frame) override
Decode and upload a video frame to the GPU.
Definition: YUV422P10.hpp:95