MayaFlux 1.0.0
Digital-First Multimedia Processing Framework
Loading...
Searching...
No Matches
VisionProcessor.cpp
Go to the documentation of this file.
1#include "VisionProcessor.hpp"
2
7
10
11namespace MayaFlux::Kakshya {
12
14 : m_sequence(std::move(sequence))
15{
17 m_executor = std::make_unique<Yantra::VisionGpuExecutor>();
18}
19
20void VisionProcessor::on_attach(const std::shared_ptr<SignalSourceContainer>& container)
21{
22 if (!container)
23 return;
24
25 const bool valid = std::dynamic_pointer_cast<VideoStreamContainer>(container)
26 || std::dynamic_pointer_cast<WindowContainer>(container)
27 || std::dynamic_pointer_cast<TextureContainer>(container);
28
29 if (!valid) {
30 error<std::invalid_argument>(
33 std::source_location::current(),
34 "VisionProcessor requires a VideoStreamContainer, WindowContainer, "
35 "or TextureContainer; got {}",
36 typeid(*container).name());
37 }
38
39 const auto& structure = container->get_structure();
40 m_width = static_cast<uint32_t>(structure.get_width());
41 m_height = static_cast<uint32_t>(structure.get_height());
42
45 } else if (m_width > 0 && m_height > 0) {
46 if (!m_executor)
47 m_executor = std::make_unique<Yantra::VisionGpuExecutor>();
48
50 m_gpu_frame = loom.create_2d(m_width, m_height, ImageFormat::RGBA8, nullptr);
52 }
53
54 if (m_width == 0 || m_height == 0) {
56 "VisionProcessor attached to container with zero spatial dimensions");
57 } else {
59 "VisionProcessor attached: {}x{}", m_width, m_height);
60 }
61}
62
63void VisionProcessor::on_detach(const std::shared_ptr<SignalSourceContainer>& /*container*/)
64{
65 m_width = 0;
66 m_height = 0;
67
70
71 m_gpu_frame.reset();
72}
73
74void VisionProcessor::process(const std::shared_ptr<SignalSourceContainer>& container)
75{
76 if (m_width == 0 || m_height == 0 || !container)
77 return;
78
79 m_is_processing.store(true, std::memory_order_release);
80
82 std::span<const float> frame;
83 if (auto vc = std::dynamic_pointer_cast<VideoStreamContainer>(container)) {
84 frame = vc->processed_frame_as_float(0);
85 vc->invalidate_float_frame_cache(0);
86 } else if (auto wc = std::dynamic_pointer_cast<WindowContainer>(container)) {
87 frame = wc->processed_frame_as_float(0);
88 wc->invalidate_float_frame_cache(0);
89 } else if (auto tc = std::dynamic_pointer_cast<TextureContainer>(container)) {
90 frame = tc->as_normalised_float(0);
91 }
92
93 if (!frame.empty())
95 } else if (m_gpu_frame) {
96 if (m_executor->is_suspended()) {
98 if (!poll.is_ready()) {
99 m_is_processing.store(false, std::memory_order_release);
100 return;
101 }
102 m_result = std::move(poll);
103 } else if (const void* raw = container->get_raw_data()) {
105 loom.upload_data(m_gpu_frame, raw, m_gpu_frame->get_size_bytes(), m_upload_staging);
106
107 auto pass = m_executor->run(m_sequence, m_gpu_frame, m_width, m_height);
108 if (!pass.is_ready()) {
109 m_is_processing.store(false, std::memory_order_release);
110 return;
111 }
112 m_result = std::move(pass);
113 }
114 }
115
116 if (m_result_source)
117 m_result_source->signal(m_result);
118
119 m_is_processing.store(false, std::memory_order_release);
120}
121
123{
124 m_sequence = std::move(sequence);
125 m_executor.reset();
127 m_result = {};
128
130 m_executor = std::make_unique<Yantra::VisionGpuExecutor>();
131 if (m_width > 0 && m_height > 0 && !m_gpu_frame) {
133 m_gpu_frame = loom.create_2d(m_width, m_height, ImageFormat::RGBA8, nullptr);
135 }
136 } else {
137 m_gpu_frame.reset();
138 m_upload_staging.reset();
139 }
140}
141
142std::shared_ptr<Vruta::BroadcastSource<Kinesis::Vision::VisionResult>> VisionProcessor::get_result_source()
143{
144 if (!m_result_source)
145 m_result_source = std::make_shared<Vruta::BroadcastSource<Kinesis::Vision::VisionResult>>();
146 return m_result_source;
147}
148} // namespace MayaFlux::Kakshya
#define MF_INFO(comp, ctx,...)
#define MF_WARN(comp, ctx,...)
std::shared_ptr< Buffers::VKBuffer > m_upload_staging
VisionProcessor(Kinesis::Vision::VisionSequence sequence)
Construct with the vision pipeline to execute each process() call.
Kinesis::Vision::VisionExecutor m_cpu_executor
std::shared_ptr< Vruta::BroadcastSource< Kinesis::Vision::VisionResult > > m_result_source
void on_attach(const std::shared_ptr< SignalSourceContainer > &container) override
Cache frame geometry from get_structure().
Kinesis::Vision::VisionSequence m_sequence
std::unique_ptr< Yantra::VisionGpuExecutor > m_executor
std::shared_ptr< Core::VKImage > m_gpu_frame
void on_detach(const std::shared_ptr< SignalSourceContainer > &container) override
Clear cached geometry and reset executor state.
void set_sequence(Kinesis::Vision::VisionSequence sequence)
Replace the pipeline and reset inter-frame executor state.
void process(const std::shared_ptr< SignalSourceContainer > &container) override
Execute the VisionSequence on processed_data[0].
std::shared_ptr< Vruta::BroadcastSource< Kinesis::Vision::VisionResult > > get_result_source()
Shared BroadcastSource signalled with each VisionResult after a successful process() call.
Kinesis::Vision::VisionResult m_result
void reset()
Clear stored inter-frame state.
VisionResult run(const VisionSequence &sequence, std::span< const float > frame, uint32_t w, uint32_t h)
Execute a VisionSequence on one frame.
std::shared_ptr< VKBuffer > create_image_staging_buffer(size_t size)
Allocate a persistent host-visible staging buffer sized for repeated streaming uploads to an image of...
@ ContainerProcessing
Container operations (Kakshya - file/stream/region processing)
@ Kakshya
Containers[Signalsource, Stream, File], Regions, DataProcessors.
@ RGBA8
Four channel 8-bit.
@ CPU
Execute the sequence with the Kinesis host executor.
@ GPU
Execute the sequence with the Yantra Vulkan executor.
VisionBackend backend
Backend used for every step.
Definition VisionOp.hpp:383
Ordered VisionSteps and the backend chosen to execute them.
Definition VisionOp.hpp:381