26 if (!std::holds_alternative<std::vector<uint8_t>>(
m_data[0])) {
27 m_data[0].emplace<std::vector<uint8_t>>();
30 return std::get<std::vector<uint8_t>>(
m_data[0]);
50 if (frame_bytes == 0) {
62 if (bytes.size() < needed) {
83 if (frame_bytes == 0 ||
pixels.size() != frame_bytes) {
85 "DynamicVideoStream::append_frame expected {} bytes, got {}", frame_bytes,
pixels.size());
94 std::memcpy(slot,
pixels.data(), frame_bytes);
100 const std::shared_ptr<Buffers::VKBuffer>& staging)
104 "DynamicVideoStream::append_frame called with an uninitialised image");
122 "DynamicVideoStream::append_frame image {}x{} does not match stream {}x{}",
128 static_cast<const uint8_t*
>(
image.data()),
image.byte_size()));
133 if (capacity == 0 || capacity > UINT32_MAX ||
m_width == 0 ||
m_height == 0) {
135 "DynamicVideoStream::enable_circular_buffer needs a capacity between 1 and {} and a non-empty frame size",
173 copy->ensure_capacity(
count);
179 copy->append_frame(
pixels.empty() ? std::span<const uint8_t>(blank) :
pixels);
187 auto processor = std::make_shared<FrameSeekProcessor>();
216 if (ring_capacity > 0) {
#define MF_ERROR(comp, ctx,...)
#define MF_WARN(comp, ctx,...)
const std::vector< float > * pixels
std::vector< uint8_t > & flat_bytes()
void enable_circular_buffer(uint64_t capacity)
Keep only the most recent capacity frames.
uint8_t * claim_frame_slot()
void ensure_capacity(uint64_t frames)
Pre-allocate room for frames in linear mode.
void publish_frame_count()
void create_default_processor() override
Install a FrameSeekProcessor as the default processor.
void lag_behind_head(double frames)
Play back a fixed number of frames behind the write head.
std::shared_ptr< DynamicVideoStream > snapshot(uint64_t frames) const
Copy the most recent frames into a new linear stream, oldest first.
void clear() override
Drop every frame and restart the write head at zero.
DynamicVideoStream(const VideoStreamSpec &spec)
Build a stream from a spec, enabling the ring when it asks for one.
bool append_frame(std::span< const uint8_t > pixels)
Write one frame at the write head and advance it.
std::shared_ptr< FrameSeekProcessor > seek_processor()
The FrameSeekProcessor that reads this stream, installed on first use.
uint8_t * mutable_slot_ptr(uint64_t frame_index)
Mutable pointer into m_data[0] for the decode thread to write into.
double get_frame_rate() const
ProcessingState get_processing_state() const override
Get the current processing state of the container.
bool is_ring_mode() const
True if the container is operating in ring mode.
void clear() override
Clear all data in the container.
std::shared_ptr< DataProcessor > get_default_processor() const override
Get the current default data processor.
void setup_ring(uint64_t total_frames, uint32_t ring_capacity, uint32_t width, uint32_t height, ImageFormat format, double frame_rate, uint32_t refill_threshold, uint64_t reader_id=0)
Allocate m_data[0] as a ring of ring_capacity frames.
std::span< const uint8_t > get_frame_pixels(uint64_t frame_index) const
Get raw pixel data for a single frame as a byte span.
Memory::Seqlock m_data_lock
std::vector< DataVariant > m_data
void set_default_processor(const std::shared_ptr< DataProcessor > &processor) override
Set the default data processor for this container.
void mark_ready_for_processing(bool ready) override
Mark the container as ready or not ready for processing.
size_t get_frame_byte_size() const
Total byte size of one frame: width * height * bytes_per_pixel.
ContainerDataStructure m_structure
uint64_t m_total_source_frames
void commit_frame(uint64_t frame_index)
Publish a decoded frame.
Concrete base implementation for streaming video containers.
RAII guard that brackets a Seqlock write region.
void download_data(const std::shared_ptr< Core::VKImage > &image, void *data, size_t size, const std::shared_ptr< Buffers::VKBuffer > &staging, bool deferred=false, vk::ImageLayout restore_layout=vk::ImageLayout::eShaderReadOnlyOptimal, vk::PipelineStageFlags restore_stage=vk::PipelineStageFlagBits::eFragmentShader)
Download pixel data from a VKImage, reusing a caller-supplied persistent staging buffer.
static TextureLoom & instance()
@ Configuration
Configuration and parameter updates.
@ 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.
std::vector< DataDimension > dimensions
Raw image data loaded from file or read back from a GPU image.
Describes a DynamicVideoStream so it can be built by designated initializer.