Loading...
Searching...
No Matches
VideoScope.hpp
1#pragma once
2#include <Process/Monitoring/Monitor.hpp>
3
4#include <QImage>
5#include <QPainter>
6
7#include <Ui/Monitor/ImageAnalysis.hpp>
8#include <Ui/Monitor/LayerHelpers.hpp>
9#include <Gfx/Widgets/OutletPreviewLayer.hpp>
10#include <Ui/Monitor/Paint.hpp>
11#include <Ui/Monitor/TextureLayers.hpp>
12#include <halp/controls.hpp>
13#include <halp/meta.hpp>
14#include <halp/texture.hpp>
15
16#include <array>
17#include <atomic>
18#include <memory>
19#include <optional>
20
21class QRhi;
22class QRhiBuffer;
23class QRhiCommandBuffer;
24class QRhiComputePipeline;
25class QRhiResourceUpdateBatch;
26class QRhiSampler;
27class QRhiShaderResourceBindings;
28class QRhiTexture;
29struct QRhiReadbackResult;
30namespace score::gfx
31{
32class RenderList;
33struct Edge;
34}
35
51namespace Ui::VideoScope
52{
53enum class Mode
54{
55 Waveform,
56 RgbOverlay,
57 RgbParade,
58 YCbCrParade,
59 Vectorscope,
60 Histogram,
61 CIE,
62 Diamond
63};
64inline constexpr std::string_view mode_names[]{
65 "Waveform", "RGB overlay", "RGB parade", "YCbCr parade",
66 "Vectorscope", "Histogram", "CIE 1931", "Diamond"};
67
68enum class Units
69{
70 Percent,
71 Code8,
72 Code10,
73 Millivolts,
74 Nits
75};
76inline constexpr std::string_view units_names[]{"%", "8-bit", "10-bit", "mV", "nits"};
77
80namespace geometry
81{
83inline double waveY(double v) noexcept
84{
85 return 1. - (v + 0.07) / 1.16;
86}
87inline QPointF vector(double cb, double cr, double zoom) noexcept
88{
89 return {0.5 + cb * zoom, 0.5 - cr * zoom};
90}
91inline QPointF cie(double x, double y) noexcept
92{
93 return {x / 0.8, 1. - y / 0.9};
94}
97inline QPointF diamondUpper(double b, double g) noexcept
98{
99 return {0.5 + (b - g) * 0.25, 0.5 - (b + g) * 0.25};
100}
101inline QPointF diamondLower(double r, double g) noexcept
102{
103 return {0.5 + (r - g) * 0.25, 0.5 + (r + g) * 0.25};
104}
105}
106
107struct Layer;
108
112{
113 std::atomic<uint32_t> clears{};
114};
115
116struct Node
117{
118 halp_meta(name, "Video scope")
119 halp_meta(c_name, "VideoScope")
120 halp_meta(category, "Monitoring/Visuals")
121 halp_meta(author, "ossia score")
122 halp_meta(manual_url, "")
123 halp_meta(
124 description,
125 "Waveform, parades, vectorscope, histogram, CIE chromaticity and diamond "
126 "scopes of a texture, computed on the GPU; the scope is also a texture")
127 halp_meta(uuid, "08283fcb-46ac-460c-b796-b3df1cb77d96")
128 halp_flag(fully_custom_item);
130
133 static constexpr int min_size = 128, max_size = 2048;
134
135 struct
136 {
137 halp::gpu_texture_input<"In"> image;
138 struct : halp::combobox_t<"Mode", Mode>
139 {
140 struct range
141 {
142 std::string_view values[8]{mode_names[0], mode_names[1], mode_names[2], mode_names[3],
143 mode_names[4], mode_names[5], mode_names[6], mode_names[7]};
144 Mode init{Mode::Waveform};
145 };
146 } mode;
147 struct : halp::combobox_t<"Matrix", Ui::Monitor::Color::Matrix>
148 {
149 halp_meta(description, "Luma and colour difference coefficients, and the primaries of the CIE plot")
150 struct range
151 {
152 std::string_view values[3]{"Rec. 601", "Rec. 709", "Rec. 2020"};
153 Ui::Monitor::Color::Matrix init{Ui::Monitor::Color::Matrix::Rec709};
154 };
155 } matrix;
156 struct : halp::combobox_t<"Transfer", Ui::Monitor::Color::Transfer>
157 {
158 halp_meta(description, "How the signal is encoded: for the CIE plot and the nits scale")
159 struct range
160 {
161 std::string_view values[3]{"SDR", "PQ", "HLG"};
162 Ui::Monitor::Color::Transfer init{Ui::Monitor::Color::Transfer::Sdr};
163 };
164 } transfer;
165 struct : halp::combobox_t<"Units", Units>
166 {
167 struct range
168 {
169 std::string_view values[5]{
170 units_names[0], units_names[1], units_names[2], units_names[3], units_names[4]};
171 Units init{Units::Percent};
172 };
173 } units;
174 struct : halp::toggle<"Legal range">
175 {
176 halp_meta(description, "Signal in narrow range: 0% at code 16 and 100% at 235 (8-bit)")
177 } legal;
178 struct : halp::hslider_f32<"Intensity", halp::range{0.1, 10., 1.}>
179 {
180 } intensity;
181 struct : halp::hslider_f32<"Persistence", halp::range{0., 0.98, 0.5}>
182 {
183 } persistence;
184 struct : halp::toggle_t<bool, "75% targets", halp::toggle_setup{.init = true}>
185 {
186 halp_meta(description, "Vectorscope targets of 75% colour bars; off for 100% bars")
187 } targets75;
188 struct : halp::hslider_f32<"Zoom", halp::range{1., 5., 1.}>
189 {
190 halp_meta(description, "Vectorscope magnification")
191 } zoom;
195 } inputs;
196
197 struct
198 {
199 halp::gpu_texture_output<"Scope"> scope;
200 } outputs;
201
202 std::shared_ptr<ScopeMonitor> monitor = std::make_shared<ScopeMonitor>();
203
204 Node();
205 ~Node();
206
207 void init(score::gfx::RenderList& r, QRhiResourceUpdateBatch& res);
208 void runInitialPasses(
209 score::gfx::RenderList& r, QRhiCommandBuffer& cb, QRhiResourceUpdateBatch*& res,
211 void release(score::gfx::RenderList& r);
212 void operator()() { }
213
214private:
215 bool createPipelines(score::gfx::RenderList& r);
218 QRhiComputePipeline* accumulate(score::gfx::RenderList& r, score::gfx::TextureKind kind);
220 void allocate(int sz);
221 bool rebuildBindings(QRhiTexture* input);
222
223 QRhi* m_rhi{};
224 QRhiBuffer* m_params{};
225 QRhiBuffer* m_bins{};
226 int size{};
227 QRhiTexture* m_out{};
229 QRhiTexture* m_overlay{};
230 int m_overlayKey{-1};
231 bool m_clearBins{};
232 uint32_t m_clears{};
233 QRhiSampler* m_sampler{};
234 QRhiShaderResourceBindings* m_srb{};
235 QRhiComputePipeline* m_decay{};
236 std::array<QRhiComputePipeline*, score::gfx::texture_kind_count> m_accumulate{};
237 std::array<bool, score::gfx::texture_kind_count> m_accumulateFailed{};
238 QRhiComputePipeline* m_render{};
239 void* m_boundInput{};
240 Ui::Monitor::Color::Transfer m_builtTransfer{};
241 bool m_pipelinesFailed{};
242};
243
248void drawGraticule(
249 QPainter& p, const QRectF& r, Mode m, Units u, bool legal,
250 Ui::Monitor::Color::Matrix matrix, Ui::Monitor::Color::Transfer transfer,
251 bool targets75, double zoom);
252
254{
255 Layer(
256 const Process::ProcessModel& process, const Process::Context& doc,
257 QGraphicsItem* parent);
258
260 void mousePressEvent(QGraphicsSceneMouseEvent* ev) override;
261
262protected:
263 void hoverMoveEvent(QGraphicsSceneHoverEvent* ev) override;
264 void hoverLeaveEvent(QGraphicsSceneHoverEvent* ev) override;
265 void paintOverlay(QPainter* p, const QRectF& image) const override;
266
267private:
268 const Process::ProcessModel& m_scope;
269 Ui::Monitor::DoubleClick m_doubleClick;
270};
271}
Definition OutletPreviewLayer.hpp:25
The Process class.
Definition score-lib-process/Process/Process.hpp:82
Definition LayerHelpers.hpp:103
List of nodes to be rendered to an output.
Definition RenderList.hpp:36
double waveY(double v) noexcept
Waveforms show from -7% to 109%, so that sub-blacks and super-whites show.
Definition VideoScope.hpp:83
QPointF diamondUpper(double b, double g) noexcept
Definition VideoScope.hpp:97
Definition VideoScope.cpp:15
void drawGraticule(QPainter &p, const QRectF &r, Mode m, Units u, bool legal, Ui::Monitor::Color::Matrix matrix, Ui::Monitor::Color::Transfer transfer, bool targets75, double zoom)
Definition VideoScope.cpp:276
Graphics rendering pipeline for ossia score.
Definition Filter/PreviewWidget.hpp:11
TextureKind
Definition TextureKind.hpp:20
Definition ProcessContext.hpp:12
Definition TextureLayers.hpp:52
Definition TextureLayers.hpp:33
Definition TextureLayers.hpp:46
Definition TextureShapeMonitor.hpp:12
Definition VideoScope.hpp:254
void mousePressEvent(QGraphicsSceneMouseEvent *ev) override
A double click clears what the scope has accumulated.
Definition VideoScope.cpp:795
void paintOverlay(QPainter *p, const QRectF &image) const override
Drawn over the image.
Definition VideoScope.cpp:817
Definition VideoScope.hpp:117
static constexpr int min_size
Definition VideoScope.hpp:133
Definition VideoScope.hpp:112
Definition MIDISync.hpp:149
Connection between two score::gfx::Port.
Definition score-plugin-gfx/Gfx/Graph/Utils.hpp:236