MayaFlux 0.2.0
Digital-First Multimedia Processing Framework
Loading...
Searching...
No Matches
FrameAccessProcessor.hpp
Go to the documentation of this file.
1#pragma once
2
6
7/**
8 * @class FrameAccessProcessor
9 * @brief Data Processor for sequential, frame-atomic access to video containers.
10 *
11 * FrameAccessProcessor is the video-domain counterpart of ContiguousAccessProcessor.
12 * Where ContiguousAccessProcessor models audio as per-channel linear streams with
13 * independent read heads, FrameAccessProcessor treats video as a sequence of
14 * indivisible spatial surfaces advanced by a single temporal cursor.
15 *
16 * A video frame is an atomic spatial unit: width × height × channels bytes of
17 * interleaved pixel data. There is no meaningful per-channel read position —
18 * RGBA planes are never consumed independently in the container→buffer pipeline.
19 * The processor therefore maintains a single frame index rather than a
20 * per-channel position vector.
21 *
22 * Output shape is four-dimensional: [frames, height, width, channels].
23 * By default the processor extracts one frame per process() call, matching the
24 * expected cadence of a downstream VideoStreamReader (the planned video
25 * analogue of SoundStreamReader) feeding a TextureBuffer.
26 *
27 * The processor writes extracted frame data into the container's processed_data
28 * vector as a single DataVariant containing contiguous uint8_t RGBA pixels.
29 * This matches VideoStreamContainer's storage convention and the Vulkan
30 * VK_FORMAT_R8G8B8A8_UNORM upload path through TextureProcessor / TextureLoom.
31 *
32 * Designed for integration into the same DataProcessingChain infrastructure
33 * used by audio, enabling mixed-domain chains where audio and video processors
34 * coexist on containers that carry both modalities.
35 *
36 * @see ContiguousAccessProcessor, VideoStreamContainer, VideoFileContainer
37 */
38namespace MayaFlux::Kakshya {
39
40class MAYAFLUX_API FrameAccessProcessor : public DataProcessor {
41public:
43 ~FrameAccessProcessor() override = default;
44
45 /**
46 * @brief Attach the processor to a video container.
47 *
48 * Reads dimension metadata (TIME, SPATIAL_Y, SPATIAL_X, CHANNEL),
49 * caches frame geometry, initialises the temporal cursor, and marks
50 * the container ready for processing.
51 *
52 * @param container The SignalSourceContainer to attach to.
53 */
54 void on_attach(const std::shared_ptr<SignalSourceContainer>& container) override;
55
56 /**
57 * @brief Detach the processor from its container.
58 * @param container The SignalSourceContainer to detach from.
59 */
60 void on_detach(const std::shared_ptr<SignalSourceContainer>& container) override;
61
62 /**
63 * @brief Extract the current frame(s) into the container's processed_data.
64 *
65 * Builds a Region spanning [m_current_frame .. m_current_frame + m_frames_per_batch)
66 * across the full spatial extent, delegates to get_region_data(), and copies
67 * the result into processed_data as a single interleaved DataVariant.
68 * Advances the frame cursor if auto-advance is enabled.
69 *
70 * @param container The SignalSourceContainer to process.
71 */
72 void process(const std::shared_ptr<SignalSourceContainer>& container) override;
73
74 /**
75 * @brief Query if the processor is currently performing processing.
76 * @return true if processing is in progress, false otherwise.
77 */
78 [[nodiscard]] bool is_processing() const override { return m_is_processing.load(); }
79
80 /**
81 * @brief Set the number of frames extracted per process() call.
82 *
83 * Defaults to 1. Values > 1 enable batch extraction for offline
84 * processing, scrubbing previews, or multi-frame compute shader dispatch.
85 *
86 * @param count Number of frames per batch.
87 */
88 void set_frames_per_batch(uint64_t count);
89
90 /**
91 * @brief Enable or disable automatic frame advancement after each process() call.
92 * @param enable true to auto-advance, false for manual control.
93 */
94 void set_auto_advance(bool enable) { m_auto_advance = enable; }
95
96 /**
97 * @brief Get the current auto-advance state.
98 * @return true if auto-advance is enabled.
99 */
100 [[nodiscard]] bool get_auto_advance() const { return m_auto_advance; }
101
102 /**
103 * @brief Set the current frame index (temporal cursor).
104 * @param frame Zero-based frame index.
105 */
106 void set_current_frame(uint64_t frame) { m_current_frame = frame; }
107
108 /**
109 * @brief Get the current frame index.
110 * @return Zero-based frame index.
111 */
112 [[nodiscard]] uint64_t get_current_frame() const { return m_current_frame; }
113
114 /**
115 * @brief Get the number of frames per batch.
116 * @return Current batch size.
117 */
118 [[nodiscard]] uint64_t get_frames_per_batch() const { return m_frames_per_batch; }
119
120 /**
121 * @brief Get the cached frame byte size (width × height × channels).
122 * @return Byte count for one frame, or 0 if not yet attached.
123 */
124 [[nodiscard]] uint64_t get_frame_byte_size() const { return m_frame_byte_size; }
125
126 void set_global_fps(double fps) { m_global_fps = fps; }
127
128private:
129 std::atomic<bool> m_is_processing { false };
130 bool m_prepared {};
131 bool m_auto_advance { true };
132
133 std::weak_ptr<SignalSourceContainer> m_source_container_weak;
134
136
137 uint64_t m_current_frame {};
138 uint64_t m_frames_per_batch { 1 };
139
140 uint64_t m_total_frames {};
141 uint64_t m_width {};
142 uint64_t m_height {};
143 uint64_t m_channels {};
144 uint64_t m_frame_byte_size {};
145 double m_global_fps { 60.0 };
146
147 bool m_looping_enabled {};
149
150 std::chrono::steady_clock::time_point m_last_process_time {};
151
152 /**
153 * @brief Sub-frame accumulator for wall-clock-driven advancement.
154 * Accumulates fractional frames between render ticks so that
155 * the video advances at its native frame_rate regardless of the
156 * render loop's FPS.
157 */
158 double m_frame_accumulator {};
159
160 /**
161 * @brief Cached video frame rate in frames per second.
162 * Set from container metadata in store_metadata().
163 */
164 double m_frame_rate {};
165
166 /**
167 * @brief Cache dimension metadata and frame geometry from the container.
168 * @param container The SignalSourceContainer to query.
169 */
170 void store_metadata(const std::shared_ptr<SignalSourceContainer>& container);
171
172 /**
173 * @brief Validate that the container is suitable for frame-based processing.
174 */
175 void validate();
176
177 /**
178 * @brief Advance the frame cursor, respecting loop boundaries.
179 * @param frames_to_advance Number of frames to step forward.
180 */
181 void advance_frame(uint64_t frames_to_advance);
182};
183
184} // namespace MayaFlux::Kakshya
Eigen::Index count
Interface for processing data within SignalSourceContainer objects.
bool is_processing() const override
Query if the processor is currently performing processing.
bool get_auto_advance() const
Get the current auto-advance state.
uint64_t get_frame_byte_size() const
Get the cached frame byte size (width × height × channels).
uint64_t get_current_frame() const
Get the current frame index.
std::weak_ptr< SignalSourceContainer > m_source_container_weak
uint64_t get_frames_per_batch() const
Get the number of frames per batch.
void set_auto_advance(bool enable)
Enable or disable automatic frame advancement after each process() call.
void set_current_frame(uint64_t frame)
Set the current frame index (temporal cursor).
Container structure for consistent dimension ordering.
Represents a point or span in N-dimensional space.
Definition Region.hpp:67