MayaFlux 1.0.0
Digital-First Multimedia Processing Framework
Loading...
Searching...
No Matches
VisionWorkflow.hpp
Go to the documentation of this file.
1#pragma once
2
3#include "VisionMatrix.hpp"
4
8
9namespace MayaFlux::Vruta {
10class TaskScheduler;
11class EventManager;
12class Event;
13}
14
15namespace MayaFlux::IO {
16class IOManager;
17}
18
19namespace MayaFlux::Buffers {
20class BufferManager;
21class TextureBuffer;
22}
23
24namespace MayaFlux::Kakshya {
25class VideoStreamContainer;
26}
27
29
31
32/**
33 * @struct LiveConfig
34 * @brief How a live workflow run is paced and which frames it delivers.
35 *
36 * With @c interval_seconds above zero the run takes a frame every interval on
37 * the graphics clock; at zero the work sets the pace.
38 *
39 * With @c apply_to set, the source is still what gets analyzed, but each
40 * analysis is applied to @c apply_to's frame of the same moment: crops,
41 * samples, annotation and tone come from that buffer instead of the analyzed
42 * frame. The buffer is read live, frame by frame, not once; when the work
43 * sets the pace its frame is copied in the tick the analyzed frame is taken.
44 */
45struct LiveConfig {
47 std::shared_ptr<Buffers::TextureBuffer> apply_to;
48};
49
50/**
51 * @struct WorkflowBufferConfig
52 * @brief What VisionWorkflow::process_to_buffer() runs: the stream to analyze,
53 * the query and extraction, where the result is drawn, and optionally
54 * how the run is paced and which buffer the analysis is applied to.
55 */
63
64/**
65 * @struct WorkflowContainerConfig
66 * @brief What VisionWorkflow::process_to_live_container() runs: the stream to
67 * analyze, the query and extraction, the collection it records into,
68 * and optionally how the run is paced and which buffer the analysis is
69 * applied to.
70 */
78
79/** @brief Picks one image from a matrix once an analysis completes; null skips it. */
80using MatrixImage = std::function<std::shared_ptr<Core::VKImage>(VisionMatrix&)>;
81
82/**
83 * @struct WorkflowStreamConfig
84 * @brief What VisionWorkflow::process_to_stream() runs: the stream to analyze,
85 * the matrix that analyzes it, the layer array the Chimera feeds, the
86 * images recorded over time, and optionally how the run is paced.
87 *
88 * @c layers gives the array's width, height, format and, as ring_frames, its
89 * layer count. @c fit places images of another extent in a layer.
90 *
91 * Each @c record entry appends what its picker returns to its collection when
92 * an analysis completes, so the collection holds only finished frames. Read
93 * it in a layer with ChimeraBuilder::from(collection, frame_rate) for lag,
94 * speed and cut, or at lag zero for the newest frame of every layer changing
95 * together.
96 */
98 std::shared_ptr<Kakshya::VideoStreamContainer> source;
99 std::shared_ptr<VisionMatrix> matrix;
101 std::optional<Portal::Graphics::FitMode> fit;
102 std::vector<std::pair<std::shared_ptr<Kakshya::TextureCollection>, MatrixImage>> record;
103 std::optional<LiveConfig> live;
104};
105
106/**
107 * @class VisionWorkflow
108 * @brief Runs vision queries over video streams, image lists and texture
109 * containers, delivering what an extraction takes from each frame.
110 *
111 * The live methods set a run going on the engine: an analysis producer on the
112 * scheduler and a delivering consumer on the event manager. They need a
113 * constructed workflow, and accept any video stream: a camera, a video file
114 * or a dynamic stream. A run keeps going until its stream reaches its end,
115 * stop_all(), the workflow's destruction, or engine shutdown. The managers
116 * are held weakly, so a workflow kept past shutdown keeps nothing alive and
117 * stops nothing.
118 *
119 * The finite methods are static: they run to completion on the calling
120 * thread and need no engine, so call them where no other vision work is
121 * running.
122 *
123 * In every method an intent set in the query without its parameters runs
124 * with the defaults, and tracking and motion carry from one frame to the
125 * next. The extraction mode must produce an image.
126 */
127class MAYAFLUX_API VisionWorkflow {
128public:
130 const std::shared_ptr<Vruta::TaskScheduler>& scheduler,
131 const std::shared_ptr<Vruta::EventManager>& event_manager,
132 const std::shared_ptr<IO::IOManager>& io_manager,
133 const std::shared_ptr<Buffers::BufferManager>& buffer_manager);
134
135 /** @brief Stops every live run this workflow started. */
137
142
143 /**
144 * @brief Run @p config's query on its source live and show what its
145 * extraction takes from each frame in a texture buffer.
146 *
147 * The stream is hooked to a buffer unless it already has one. Without a
148 * live config, or with an interval of zero, the work sets the pace: the
149 * analysis advances one sequence per graphics tick without waiting on
150 * deferred flow steps. A stream that is not looping stops the run at its
151 * end. The output buffer takes the source's size, or the apply_to
152 * buffer's when one is set.
153 *
154 * @return The output buffer, or null with a logged reason when the
155 * engine's managers are gone or the stream cannot be hooked.
156 */
157 [[nodiscard]] std::shared_ptr<Buffers::TextureBuffer> process_to_buffer(
158 const WorkflowBufferConfig& config);
159
160 /**
161 * @brief Run @p config's query on its source live and record what its
162 * extraction takes from each frame into a growing collection.
163 *
164 * Paced and sourced as process_to_buffer(). Each extracted image is
165 * copied into the next layer; frames whose extraction gives no image add
166 * nothing. A width or height of zero in the collection spec takes the
167 * source's, or the apply_to buffer's. Recording stops for good at the
168 * stream's end, once the collection is full under its byte cap, or when
169 * the caller releases it. A ring keeps the newest frames instead.
170 *
171 * @return The collection, filling as frames arrive, or null with a logged
172 * reason when the engine's managers are gone or the stream cannot
173 * be hooked.
174 */
175 [[nodiscard]] std::shared_ptr<Kakshya::TextureCollection> process_to_live_container(
176 const WorkflowContainerConfig& config);
177
178 /**
179 * @brief process_to_buffer() with a matrix the caller made and configured,
180 * such as its extractor's sizes, focus or limits.
181 *
182 * The matrix must have an extractor whose mode produces an image.
183 *
184 * @return The output buffer, or null when @p matrix is null or as
185 * process_to_buffer() fails.
186 */
187 [[nodiscard]] std::shared_ptr<Buffers::TextureBuffer> process_to_buffer(
188 const std::shared_ptr<VisionMatrix>& matrix,
189 const std::shared_ptr<Kakshya::VideoStreamContainer>& source,
190 const Portal::Graphics::RenderConfig& render,
191 const std::optional<LiveConfig>& live = {});
192
193 /**
194 * @brief process_to_live_container() with a matrix the caller made and
195 * configured.
196 *
197 * @return The collection, or null when @p matrix is null or as
198 * process_to_live_container() fails.
199 */
200 [[nodiscard]] std::shared_ptr<Kakshya::TextureCollection> process_to_live_container(
201 const std::shared_ptr<VisionMatrix>& matrix,
202 const std::shared_ptr<Kakshya::VideoStreamContainer>& source,
204 const std::optional<LiveConfig>& live = {});
205
206 /**
207 * @brief Run @p config's matrix on its source live and return a Chimera
208 * builder over a new layer array, for any image the run produces.
209 *
210 * Paced and sourced as process_to_buffer(). The layers, their sources and
211 * the rendering are declared on the returned builder, and the array itself,
212 * for a shader's mode, is its get_buffer(). Each analysis is
213 * handed to the matrix's extract(), so its analysis(), frame() and
214 * extraction() follow the run; the images of every sequence are read from
215 * its results() or, by intent, result(). Then each record entry appends
216 * its picked image, all together once per analysis, at the run's pace:
217 * one per interval, or as often as the work completes, which the matrix
218 * reports as analysis_rate(). The run stops as the other live runs do,
219 * and also once the Chimera that was started from the builder is stopped
220 * or dropped, or the builder is dropped unstarted. The Chimera outlives
221 * the run and keeps its last images.
222 *
223 * @return The builder, or one without an array when the engine's managers
224 * are gone, the matrix is null or the stream cannot be hooked.
225 */
226 [[nodiscard]] Kriya::ChimeraBuilder process_to_stream(const WorkflowStreamConfig& config);
227
228 /**
229 * @brief Stop every live run this workflow started and release what they
230 * hold. Outputs already returned keep their content.
231 */
232 void stop_all();
233
234 /**
235 * @brief Run @p query over @p frames in order and record what @p extract
236 * takes from each into a collection.
237 *
238 * Null frames, and frames whose extraction gives no image, add no layer.
239 * A width or height of zero in @p spec takes the first frame's; its byte
240 * cap and ring are not used.
241 *
242 * @return The filled collection, or null when @p frames holds no image.
243 */
244 [[nodiscard]] static std::shared_ptr<Kakshya::TextureCollection> process_to_container(
245 const std::vector<std::shared_ptr<Core::VKImage>>& frames,
247 VisionExtractMode extract,
249
250 /**
251 * @brief Run @p query over the layers of @p frames in order and record
252 * what @p extract takes from each into a collection.
253 *
254 * Same as the image list overload, with the layers as the frames. A width
255 * or height of zero in @p spec takes the container's.
256 *
257 * @return The filled collection, or null when @p frames is null.
258 */
259 [[nodiscard]] static std::shared_ptr<Kakshya::TextureCollection> process_to_container(
260 const std::shared_ptr<Kakshya::TextureContainer>& frames,
261 Kinesis::Vision::VisionQuery query,
262 VisionExtractMode extract,
263 Kakshya::TextureCollectionSpec spec = {});
264
265private:
266 std::weak_ptr<Vruta::TaskScheduler> m_scheduler;
267 std::weak_ptr<Vruta::EventManager> m_event_manager;
268 std::weak_ptr<IO::IOManager> m_io_manager;
269 std::weak_ptr<Buffers::BufferManager> m_buffer_manager;
270
271 /** @brief Per live run: its producer task's name and its consumer. */
272 std::vector<std::pair<std::string, std::weak_ptr<Vruta::Event>>> m_runs;
273
274 [[nodiscard]] std::shared_ptr<Buffers::TextureBuffer> source_frames(
275 const std::shared_ptr<Kakshya::VideoStreamContainer>& source,
276 std::string_view caller) const;
277
278 void keep(const std::string& name, const std::shared_ptr<Vruta::Event>& consumer);
279
280 /**
281 * @brief Subscribe @p consumer and start the producer named @p name,
282 * which stops the run at @p source's end, or once @p stop_when
283 * reports true when it is given.
284 */
285 void start(
286 const std::shared_ptr<Kakshya::VideoStreamContainer>& source,
287 const std::shared_ptr<Buffers::TextureBuffer>& frames,
288 const LiveConfig& live,
289 const std::shared_ptr<VisionMatrix>& matrix,
290 const std::string& name,
291 std::function<void(const VisionIO&)> consumer,
292 std::function<bool()> stop_when = {});
293};
294
295} // namespace MayaFlux::Yantra::Vision
std::string name
Definition VKDevice.cpp:123
Declares the layers of a Chimera, in order, and starts feeding them.
Definition Chimera.hpp:190
Compute matrix holding one VisionAnalyzer for a query and, when an extraction mode is given,...
VisionWorkflow(const VisionWorkflow &)=delete
VisionWorkflow & operator=(VisionWorkflow &&)=delete
VisionWorkflow & operator=(const VisionWorkflow &)=delete
std::weak_ptr< Vruta::EventManager > m_event_manager
VisionWorkflow(VisionWorkflow &&)=delete
std::weak_ptr< Vruta::TaskScheduler > m_scheduler
std::vector< std::pair< std::string, std::weak_ptr< Vruta::Event > > > m_runs
Per live run: its producer task's name and its consumer.
std::weak_ptr< Buffers::BufferManager > m_buffer_manager
std::weak_ptr< IO::IOManager > m_io_manager
Runs vision queries over video streams, image lists and texture containers, delivering what an extrac...
std::function< std::shared_ptr< Core::VKImage >(VisionMatrix &)> MatrixImage
Picks one image from a matrix once an analysis completes; null skips it.
Datum< std::shared_ptr< Kakshya::SignalSourceContainer > > ContainerIO
IO for signal containers.
Definition DataIO.hpp:384
VisionExtractMode
Which method run_operation dispatches to.
Describes a TextureCollection so it can be built by designated initializer.
Describes a DynamicVideoStream so it can be built by designated initializer.
Composed query: which VisionIntents are active, and each active one's parameters.
Unified rendering configuration for graphics buffers.
Input/Output container for computation pipeline data flow with structure preservation.
Definition DataIO.hpp:26
std::shared_ptr< Buffers::TextureBuffer > apply_to
How a live workflow run is paced and which frames it delivers.
std::shared_ptr< Kakshya::VideoStreamContainer > source
What VisionWorkflow::process_to_buffer() runs: the stream to analyze, the query and extraction,...
std::shared_ptr< Kakshya::VideoStreamContainer > source
What VisionWorkflow::process_to_live_container() runs: the stream to analyze, the query and extractio...
std::vector< std::pair< std::shared_ptr< Kakshya::TextureCollection >, MatrixImage > > record
std::shared_ptr< Kakshya::VideoStreamContainer > source
std::optional< Portal::Graphics::FitMode > fit
What VisionWorkflow::process_to_stream() runs: the stream to analyze, the matrix that analyzes it,...