MayaFlux 0.4.0
Digital-First Multimedia Processing Framework
Loading...
Searching...
No Matches
SpatialRegionProcessor.cpp
Go to the documentation of this file.
2
6
7namespace MayaFlux::Kakshya {
8
9void SpatialRegionProcessor::on_attach(const std::shared_ptr<SignalSourceContainer>& container)
10{
11 if (!container) {
12 error<std::invalid_argument>(
15 std::source_location::current(),
16 "SpatialRegionProcessor: container must not be null");
17 }
18
19 const auto& dims = container->get_structure().dimensions;
20 const bool has_spatial = std::ranges::any_of(dims, [](const DataDimension& d) {
24 });
25
26 if (!has_spatial) {
27 error<std::invalid_argument>(
30 std::source_location::current(),
31 "SpatialRegionProcessor: container must have at least one spatial dimension");
32 }
33
34 m_auto_caching = false;
35
37
39 "SpatialRegionProcessor attached ({} region(s) across {} group(s))",
41 container->get_all_region_groups().size());
42}
43
44void SpatialRegionProcessor::on_detach(const std::shared_ptr<SignalSourceContainer>& container)
45{
47}
48
49// =========================================================================
50// organize_container_data
51// =========================================================================
52
54 const std::shared_ptr<SignalSourceContainer>& container)
55{
56 m_organized_regions.clear();
57
58 const auto groups = container->get_all_region_groups();
59
60 for (const auto& [group_name, group] : groups) {
61 for (size_t i = 0; i < group.regions.size(); ++i) {
62 OrganizedRegion org(group_name, static_cast<uint32_t>(i));
63
64 std::ranges::copy(group.attributes,
65 std::inserter(org.attributes, org.attributes.end()));
66 std::ranges::copy(group.regions[i].attributes,
67 std::inserter(org.attributes, org.attributes.end()));
68
69 org.attributes["group_name"] = group_name;
70 org.attributes["region_index"] = i;
71
72 org.segments.emplace_back(group.regions[i]);
74
75 m_organized_regions.push_back(std::move(org));
76 }
77 }
78}
79
80// =========================================================================
81// process
82// =========================================================================
83
84void SpatialRegionProcessor::process(const std::shared_ptr<SignalSourceContainer>& container)
85{
86 if (!container) {
88 "SpatialRegionProcessor::process — null container");
89 return;
90 }
91
92 auto& processed = container->get_processed_data();
93
94 if (processed.empty()) {
96 "SpatialRegionProcessor: processed_data empty, no readback available");
97 container->update_processing_state(ProcessingState::IDLE);
98 return;
99 }
100
101 const bool src_empty = std::visit(
102 [](const auto& v) { return v.empty(); }, processed[0]);
103
104 if (src_empty) {
106 "SpatialRegionProcessor: processed_data[0] empty, skipping extraction");
107 container->update_processing_state(ProcessingState::IDLE);
108 return;
109 }
110
111 if (m_organized_regions.empty()) {
112 container->update_processing_state(ProcessingState::IDLE);
113 return;
114 }
115
116 m_is_processing.store(true, std::memory_order_release);
117 container->update_processing_state(ProcessingState::PROCESSING);
118
119 const auto& dims = container->get_structure().dimensions;
120
121 std::vector<DataVariant> extracts;
122 extracts.reserve(m_organized_regions.size());
123
124 std::visit([&](const auto& src_vec) {
125 using T = typename std::decay_t<decltype(src_vec)>::value_type;
126
127 if constexpr (std::is_same_v<T, uint8_t>
128 || std::is_same_v<T, uint16_t>
129 || std::is_same_v<T, uint32_t>
130 || std::is_same_v<T, float>) {
131
132 const std::span<const T> src { src_vec.data(), src_vec.size() };
133
134 for (auto& org : m_organized_regions) {
135 if (org.segments.empty()) {
137 "SpatialRegionProcessor: OrganizedRegion '{}[{}]' has no segments, skipping",
138 org.group_name, org.region_index);
139 continue;
140 }
141
142 org.state = RegionState::ACTIVE;
143
144 try {
145 extracts.emplace_back(
146 extract_nd_region<T>(src, org.segments[0].source_region, dims));
147 org.state = RegionState::READY;
148 } catch (const std::exception& e) {
150 "SpatialRegionProcessor: extraction failed for '{}[{}]' — {}",
151 org.group_name, org.region_index, e.what());
152 org.state = RegionState::IDLE;
153 }
154 }
155 } else {
157 "SpatialRegionProcessor: processed_data[0] holds a type not suitable "
158 "for spatial pixel extraction ({}); no regions extracted",
159 typeid(T).name());
160 }
161 },
162 processed[0]);
163
164 processed = std::move(extracts);
165
166 m_is_processing.store(false, std::memory_order_release);
167 container->update_processing_state(ProcessingState::PROCESSED);
168}
169
170// =========================================================================
171// refresh
172// =========================================================================
173
175{
176 if (auto container = m_container_weak.lock()) {
177 organize_container_data(container);
178
180 "SpatialRegionProcessor: refreshed ({} region(s))",
181 m_organized_regions.size());
182 }
183}
184
185} // namespace MayaFlux::Kakshya
#define MF_INFO(comp, ctx,...)
#define MF_RT_WARN(comp, ctx,...)
#define MF_RT_ERROR(comp, ctx,...)
#define MF_RT_TRACE(comp, ctx,...)
std::vector< OrganizedRegion > m_organized_regions
void on_detach(const std::shared_ptr< SignalSourceContainer > &container) override
Detach this processor from its container.
void on_attach(const std::shared_ptr< SignalSourceContainer > &container) override
Attach this processor to a signal source container.
std::weak_ptr< SignalSourceContainer > m_container_weak
void organize_container_data(const std::shared_ptr< SignalSourceContainer > &container) override
Build m_organized_regions from get_all_region_groups().
void process(const std::shared_ptr< SignalSourceContainer > &container) override
Extract all active regions from processed_data[0] in parallel.
void refresh()
Re-sync m_organized_regions from the container's current group map.
void on_attach(const std::shared_ptr< SignalSourceContainer > &container) override
Attach to a spatial container.
void on_detach(const std::shared_ptr< SignalSourceContainer > &container) override
Detach; delegates to RegionProcessorBase::on_detach.
@ ContainerProcessing
Container operations (Kakshya - file/stream/region processing)
@ Kakshya
Containers[Signalsource, Stream, File], Regions, DataProcessors.
@ IDLE
Container is inactive with no data or not ready for processing.
@ PROCESSING
Container is actively being processed.
@ PROCESSED
Container has completed processing and results are available.
@ ACTIVE
Currently being processed.
@ READY
Ready for processing.
@ IDLE
Not being processed.
@ SPATIAL_X
Spatial X axis (images, tensors)
Role role
Semantic hint for common operations.
Definition NDData.hpp:194
Minimal dimension descriptor focusing on structure only.
Definition NDData.hpp:142
std::unordered_map< std::string, std::any > attributes
Extensible metadata.
std::vector< RegionSegment > segments
Audio segments in this region.
A structured audio region with metadata and transition information.