MayaFlux 0.4.0
Digital-First Multimedia Processing Framework
Loading...
Searching...
No Matches
IOManager.cpp
Go to the documentation of this file.
1#include "IOManager.hpp"
2
5
7
13
17
20
23
24#include "EXRWriter.hpp"
25#include "ImageExport.hpp"
26#include "ModelReader.hpp"
27#include "STBImageWriter.hpp"
28
30
31extern "C" {
32#include <libavdevice/avdevice.h>
33}
34
35namespace MayaFlux::IO {
36
37namespace {
38
39 TextureResolver make_default_resolver(const std::string& filepath)
40 {
41 const auto base_dir = std::filesystem::path(filepath).parent_path();
42 return [base_dir](const std::string& raw) -> std::shared_ptr<Core::VKImage> {
43 auto tex_path = FileReader::resolve_path((base_dir / raw).generic_string());
44 return IO::ImageReader::load_texture(tex_path);
45 };
46 }
47
48}
49
50IOManager::IOManager(uint64_t sample_rate, uint32_t buffer_size, uint32_t frame_rate, const std::shared_ptr<Buffers::BufferManager>& buffer_manager)
51 : m_sample_rate(sample_rate)
52 , m_buffer_size(buffer_size)
53 , m_frame_rate(frame_rate)
54 , m_buffer_manager(buffer_manager)
55{
56 m_io_service = std::make_shared<Registry::Service::IOService>();
57
58 m_io_service->request_decode = [this](uint64_t reader_id) {
59 dispatch_decode_request(reader_id);
60 };
61
64 [svc = m_io_service]() -> void* { return svc.get(); });
65
66 m_io_service->request_frame = [this](uint64_t reader_id) {
67 dispatch_frame_request(reader_id);
68 };
69
72
74}
75
77{
80
81 m_io_service.reset();
82
83 {
84 std::unique_lock lock(m_readers_mutex);
85 m_video_readers.clear();
86 }
87
88 {
89 std::unique_lock lock(m_camera_mutex);
90 m_camera_readers.clear();
91 }
92
93 {
94 std::unique_lock lock(m_buffers_mutex);
95 m_video_buffers.clear();
96 m_audio_buffers.clear();
97 }
98
100}
101
102std::shared_ptr<Kakshya::VideoFileContainer>
103IOManager::load_video(const std::string& filepath)
104{
105 return load_video(filepath, {}).video;
106}
107
109IOManager::load_video(const std::string& filepath, LoadConfig config)
110{
111 auto reader = std::make_shared<IO::VideoFileReader>();
112
113 if (!reader->can_read(filepath)) {
115 "Cannot read video file: {}", filepath);
116 return {};
117 }
118
119 reader->set_video_options(config.video_options);
120 reader->set_audio_options(config.audio_options);
121 reader->set_target_dimensions(config.target_width, config.target_height);
122
124 reader->set_target_sample_rate(m_sample_rate);
125 }
126
127 if (!reader->open(filepath, config.file_options)) {
129 "Failed to open video file: {}", reader->get_last_error());
130 return {};
131 }
132
133 const uint64_t reader_id = register_video_reader(reader);
134 reader->setup_io_service(reader_id);
135
136 auto video_container = std::dynamic_pointer_cast<Kakshya::VideoFileContainer>(reader->create_container());
137
138 if (!video_container) {
140 "Failed to create video container from: {}", filepath);
141 release_video_reader(reader_id);
142 return {};
143 }
144
145 if (!reader->load_into_container(video_container)) {
147 "Failed to load video data: {}", reader->get_last_error());
148 release_video_reader(reader_id);
149 return {};
150 }
151
152 configure_frame_processor(video_container);
153
154 VideoLoadResult result;
155 result.video = video_container;
156
158 auto audio_container = reader->get_audio_container();
159 if (audio_container) {
160 configure_audio_processor(audio_container);
161 result.audio = audio_container;
162 m_extracted_audio[video_container] = audio_container;
163 } else {
165 "No audio track found in: {}", filepath);
166 }
167 }
168
170 "Loaded video: {}", filepath);
171
172 return result;
173}
174
175uint64_t IOManager::register_video_reader(std::shared_ptr<IO::VideoFileReader> reader)
176{
177 if (!reader) {
179 "IOManager::register_video_reader called with null reader");
180 return 0;
181 }
182
183 const uint64_t id = m_next_reader_id.fetch_add(1, std::memory_order_relaxed);
184 reader->set_reader_id(id);
185
186 {
187 std::unique_lock lock(m_readers_mutex);
188 m_video_readers.emplace(id, std::move(reader));
189 }
190
192 "IOManager: registered VideoFileReader id={}", id);
193
194 return id;
195}
196
197void IOManager::release_video_reader(uint64_t reader_id)
198{
199 std::unique_lock lock(m_readers_mutex);
200 auto it = m_video_readers.find(reader_id);
201
202 if (it == m_video_readers.end()) {
204 "IOManager::release_video_reader: unknown id={}", reader_id);
205 return;
206 }
207
208 m_video_readers.erase(it);
209
211 "IOManager: released VideoFileReader id={}", reader_id);
212}
213
215{
216 std::shared_lock lock(m_readers_mutex);
217 auto it = m_video_readers.find(reader_id);
218
219 if (it == m_video_readers.end()) {
221 "IOManager: dispatch_decode_request unknown reader_id={}", reader_id);
222 return;
223 }
224
225 it->second->signal_decode();
226}
227
228void IOManager::dispatch_frame_request(uint64_t reader_id)
229{
230 std::shared_lock lock(m_camera_mutex);
231 auto it = m_camera_readers.find(reader_id);
232
233 if (it == m_camera_readers.end()) {
235 "IOManager: dispatch_frame_request unknown reader_id={}", reader_id);
236 return;
237 }
238
239 it->second->pull_frame_all();
240}
241
242std::shared_ptr<Kakshya::SoundFileContainer> IOManager::load_audio(const std::string& filepath, LoadConfig config)
243{
244 auto reader = std::make_shared<IO::SoundFileReader>();
245
246 if (!reader->can_read(filepath)) {
247 MF_ERROR(Journal::Component::API, Journal::Context::FileIO, "Cannot read file: {}", filepath);
248 return nullptr;
249 }
250
251 reader->set_target_sample_rate(m_sample_rate);
252 reader->set_audio_options(config.audio_options);
253
254 if (!reader->open(filepath, config.file_options)) {
255 MF_ERROR(Journal::Component::API, Journal::Context::FileIO, "Failed to open file: {}", reader->get_last_error());
256 return nullptr;
257 }
258
259 auto container = reader->create_container();
260 auto sound_container = std::dynamic_pointer_cast<Kakshya::SoundFileContainer>(container);
261 if (!sound_container) {
262 MF_ERROR(Journal::Component::API, Journal::Context::Runtime, "Failed to create sound container");
263 return nullptr;
264 }
265
266 if (!reader->load_into_container(sound_container)) {
267 MF_ERROR(Journal::Component::API, Journal::Context::Runtime, "Failed to load audio data: {}", reader->get_last_error());
268 return nullptr;
269 }
270
271 configure_audio_processor(sound_container);
272
273 m_audio_readers.push_back(std::move(reader));
274
275 return sound_container;
276}
277
278std::shared_ptr<Kakshya::DynamicSoundStream> IOManager::load_audio_bounded(
279 const std::string& filepath,
280 uint64_t max_frames,
281 bool truncate)
282{
283 auto reader = std::make_shared<IO::SoundFileReader>();
284
285 if (!reader->can_read(filepath)) {
287 "IOManager::load_bounded: unsupported format '{}'", filepath);
288 return nullptr;
289 }
290
291 reader->set_target_sample_rate(m_sample_rate);
292
293 auto stream = reader->load_bounded(filepath, max_frames, truncate);
294 if (!stream) {
296 "IOManager::load_bounded: failed for '{}'", filepath);
297 return nullptr;
298 }
299
300 stream->set_memory_layout(Kakshya::MemoryLayout::ROW_MAJOR);
301
302 m_audio_readers.push_back(std::move(reader));
303
304 return stream;
305}
306
307std::shared_ptr<Kakshya::CameraContainer>
309{
310 static std::once_flag s_avdevice_init;
311 std::call_once(s_avdevice_init, [] { avdevice_register_all(); });
312
313 auto reader = std::make_shared<CameraReader>();
314
315 if (!reader->open(config)) {
317 "open_camera: failed — {}", reader->last_error());
318 return nullptr;
319 }
320
321 auto container = reader->create_container();
322 if (!container) {
324 "open_camera: failed to create container — {}",
325 reader->last_error());
326 return nullptr;
327 }
328
329 container->create_default_processor();
330
331 uint64_t rid = m_next_reader_id.fetch_add(1, std::memory_order_relaxed);
332 reader->set_container(container);
333
334 {
335 std::unique_lock lock(m_camera_mutex);
336 m_camera_readers[rid] = reader;
337 }
338
339 container->setup_io(rid);
340 container->mark_ready_for_processing(true);
341
343 "open_camera: reader_id={} device='{}' {}x{} @{:.1f}fps",
344 rid, config.device_name,
345 reader->width(), reader->height(), reader->frame_rate());
346
347 return container;
348}
349
350std::shared_ptr<Buffers::TextureBuffer>
351IOManager::load_image(const std::string& filepath)
352{
353 auto reader = std::make_shared<IO::ImageReader>();
354
355 if (!reader->open(filepath)) {
357 "Failed to open image: {}", filepath);
358 return nullptr;
359 }
360
361 auto texture_buffer = reader->create_texture_buffer();
362
363 if (!texture_buffer) {
365 "Failed to create texture buffer from: {}", filepath);
366 return nullptr;
367 }
368
369 m_image_readers.push_back(std::move(reader));
370
372 "Loaded image: {} ({}x{})",
373 std::filesystem::path(filepath).filename().string(),
374 texture_buffer->get_width(),
375 texture_buffer->get_height());
376
377 return texture_buffer;
378}
379
380std::vector<std::shared_ptr<Buffers::MeshBuffer>>
381IOManager::load_mesh(const std::string& filepath, TextureResolver resolver)
382{
383 auto reader = std::make_shared<ModelReader>();
384
385 if (!reader->can_read(filepath)) {
387 "IOManager::load_mesh: unsupported format '{}'", filepath);
388 return {};
389 }
390
391 if (!reader->open(filepath)) {
393 "IOManager::load_mesh: failed to open '{}' — {}",
394 filepath, reader->get_last_error());
395 return {};
396 }
397
398 if (!resolver)
399 resolver = make_default_resolver(filepath);
400
401 auto buffers = reader->create_mesh_buffers(resolver);
402 reader->close();
403
404 if (buffers.empty()) {
406 "IOManager::load_mesh: no meshes in '{}'", filepath);
407 return {};
408 }
409
411 "IOManager::load_mesh: {} mesh(es) from '{}'",
412 buffers.size(),
413 std::filesystem::path(filepath).filename().string());
414
415 return buffers;
416}
417
418std::shared_ptr<Nodes::Network::MeshNetwork>
419IOManager::load_mesh_network(const std::string& filepath, TextureResolver resolver)
420{
421 auto reader = std::make_shared<ModelReader>();
422
423 if (!reader->can_read(filepath)) {
425 "IOManager::load_mesh_network: unsupported format '{}'", filepath);
426 return nullptr;
427 }
428
429 if (!reader->open(filepath)) {
431 "IOManager::load_mesh_network: failed to open '{}' — {}",
432 filepath, reader->get_last_error());
433 return nullptr;
434 }
435
436 if (!resolver)
437 resolver = make_default_resolver(filepath);
438
439 auto net = reader->create_mesh_network(resolver);
440 reader->close();
441
442 if (!net) {
444 "IOManager::load_mesh_network: no network from '{}'", filepath);
445 return nullptr;
446 }
447
449 "IOManager::load_mesh_network: {} slots from '{}'",
450 net->slot_count(),
451 std::filesystem::path(filepath).filename().string());
452
453 return net;
454}
455
457 const std::shared_ptr<Kakshya::VideoFileContainer>& container)
458{
459 auto existing = std::dynamic_pointer_cast<Kakshya::FrameAccessProcessor>(
460 container->get_default_processor());
461
462 if (existing) {
463 existing->set_global_fps(m_frame_rate);
464 existing->set_auto_advance(true);
466 "Configured existing FrameAccessProcessor");
467 } else {
468 auto processor = std::make_shared<Kakshya::FrameAccessProcessor>();
469 processor->set_global_fps(m_frame_rate);
470 processor->set_auto_advance(true);
471 container->set_default_processor(processor);
473 "Created and set FrameAccessProcessor");
474 }
475}
476
478 const std::shared_ptr<Kakshya::SoundFileContainer>& container)
479{
480 container->set_memory_layout(Kakshya::MemoryLayout::ROW_MAJOR);
481
482 const std::vector<uint64_t> output_shape = {
484 container->get_num_channels()
485 };
486
487 auto existing = std::dynamic_pointer_cast<Kakshya::ContiguousAccessProcessor>(
488 container->get_default_processor());
489
490 if (existing) {
491 existing->set_output_size(output_shape);
492 existing->set_auto_advance(true);
494 "Configured existing ContiguousAccessProcessor");
495 } else {
496 auto processor = std::make_shared<Kakshya::ContiguousAccessProcessor>();
497 processor->set_output_size(output_shape);
498 processor->set_auto_advance(true);
499 container->set_default_processor(processor);
501 "Created and set ContiguousAccessProcessor");
502 }
503}
504
505std::shared_ptr<Buffers::VideoContainerBuffer>
507 const std::shared_ptr<Kakshya::VideoFileContainer>& container)
508{
509 if (!container) {
511 "hook_video_container_to_buffer: null container");
512 return nullptr;
513 }
514
515 auto stream_container = std::dynamic_pointer_cast<Kakshya::StreamContainer>(container);
516
517 if (!stream_container) {
519 "hook_video_container_to_buffer: container is not a VideoStreamContainer");
520 return nullptr;
521 }
522
523 auto video_buffer = m_buffer_manager->create_graphics_buffer<Buffers::VideoContainerBuffer>(
525 stream_container);
526
527 {
528 std::unique_lock lock(m_buffers_mutex);
529 m_video_buffers[container] = video_buffer;
530 }
531
533 "Hooked VideoFileContainer to VideoContainerBuffer ({}x{})",
534 video_buffer->get_width(), video_buffer->get_height());
535
536 return video_buffer;
537}
538
539std::vector<std::shared_ptr<Buffers::SoundContainerBuffer>>
541 const std::shared_ptr<Kakshya::SoundFileContainer>& container)
542{
543 if (!container) {
545 "hook_audio_container_to_buffers: null container");
546 return {};
547 }
548
549 uint32_t num_channels = container->get_num_channels();
550 std::vector<std::shared_ptr<Buffers::SoundContainerBuffer>> created_buffers;
551
552 MF_TRACE(
555 "Setting up audio playback for {} channels...",
556 num_channels);
557
558 for (uint32_t channel = 0; channel < num_channels; ++channel) {
559 auto container_buffer = m_buffer_manager->create_audio_buffer<MayaFlux::Buffers::SoundContainerBuffer>(
561 channel,
562 container,
563 channel);
564
565 container_buffer->initialize();
566
567 created_buffers.push_back(std::move(container_buffer));
568
569 MF_INFO(
572 "✓ Created buffer for channel {}",
573 channel);
574 }
575
576 m_audio_buffers[container] = created_buffers;
577
578 return created_buffers;
579}
580
581std::shared_ptr<Buffers::VideoContainerBuffer>
583 const std::shared_ptr<Kakshya::CameraContainer>& container)
584{
585 if (!container) {
587 "hook_camera_to_buffer: null container");
588 return nullptr;
589 }
590
591 auto stream_container = std::dynamic_pointer_cast<Kakshya::StreamContainer>(container);
592 if (!stream_container) {
594 "hook_camera_to_buffer: container is not a StreamContainer");
595 return nullptr;
596 }
597
598 auto video_buffer = m_buffer_manager->create_graphics_buffer<Buffers::VideoContainerBuffer>(
600 stream_container);
601
602 if (!video_buffer) {
604 "hook_camera_to_buffer: failed to create VideoContainerBuffer");
605 return nullptr;
606 }
607
608 {
609 std::unique_lock lock(m_camera_mutex);
610 m_camera_buffers[container] = video_buffer;
611 }
612
614 "Hooked CameraContainer to VideoContainerBuffer ({}x{})",
615 video_buffer->get_width(), video_buffer->get_height());
616
617 return video_buffer;
618}
619
620std::shared_ptr<Buffers::VideoContainerBuffer>
622 const std::shared_ptr<Kakshya::VideoFileContainer>& container) const
623{
624 std::shared_lock lock(m_buffers_mutex);
625 auto it = m_video_buffers.find(container);
626 return it != m_video_buffers.end() ? it->second : nullptr;
627}
628
629std::vector<std::shared_ptr<Buffers::SoundContainerBuffer>>
631 const std::shared_ptr<Kakshya::SoundFileContainer>& container) const
632{
633 std::shared_lock lock(m_buffers_mutex);
634 auto it = m_audio_buffers.find(container);
635 return it != m_audio_buffers.end() ? it->second : std::vector<std::shared_ptr<Buffers::SoundContainerBuffer>> {};
636}
637
638std::shared_ptr<Kakshya::SoundFileContainer>
639IOManager::get_extracted_audio(const std::shared_ptr<Kakshya::VideoFileContainer>& container) const
640{
641 std::shared_lock lock(m_buffers_mutex);
642 auto it = m_extracted_audio.find(container);
643 return it != m_extracted_audio.end() ? it->second : nullptr;
644}
645
646std::shared_ptr<Buffers::VideoContainerBuffer>
648 const std::shared_ptr<Kakshya::CameraContainer>& container) const
649{
650 std::shared_lock lock(m_camera_mutex);
651 auto it = m_camera_buffers.find(container);
652 return it != m_camera_buffers.end() ? it->second : nullptr;
653}
654
656 const std::shared_ptr<Core::VKImage>& image,
657 const std::string& filepath,
658 const IO::ImageWriteOptions& options)
659{
660 if (!image) {
662 "save_image: null image");
663 return false;
664 }
665
666 auto fut = std::async(std::launch::async,
667 [image, filepath, options]() -> bool {
668 auto data = IO::download_image(image);
669 if (!data) {
671 "save_image task: download failed for '{}'", filepath);
672 return false;
673 }
674
675 auto writer = IO::ImageWriterRegistry::instance().create_writer(filepath);
676 if (!writer) {
678 "save_image task: no writer registered for '{}'", filepath);
679 return false;
680 }
681
682 const bool ok = writer->write(filepath, *data, options);
683 if (!ok) {
685 "save_image task: writer failed for '{}': {}",
686 filepath, writer->get_last_error());
687 } else {
689 "save_image task: wrote '{}'", filepath);
690 }
691 return ok;
692 });
693
694 std::lock_guard lock(m_save_tasks_mutex);
695 m_save_tasks.push_back(std::move(fut));
696
697 std::erase_if(m_save_tasks, [](std::future<bool>& f) {
698 return f.wait_for(std::chrono::seconds(0)) == std::future_status::ready;
699 });
700
701 return true;
702}
703
705 const std::shared_ptr<Buffers::TextureBuffer>& buffer,
706 const std::string& filepath,
707 const IO::ImageWriteOptions& options)
708{
709 if (!buffer) {
711 "save_image: null buffer");
712 return false;
713 }
714 auto image = buffer->get_gpu_texture();
715 if (!image) {
717 "save_image: buffer has no GPU texture");
718 return false;
719 }
720 return save_image(image, filepath, options);
721}
722
724 const std::shared_ptr<Buffers::TextBuffer>& buffer,
725 const std::string& filepath,
726 const IO::ImageWriteOptions& options)
727{
728 return save_image(
729 std::static_pointer_cast<Buffers::TextureBuffer>(buffer),
730 filepath,
731 options);
732}
733
735 IO::ImageData data,
736 const std::string& filepath,
737 const IO::ImageWriteOptions& options)
738{
739 auto fut = std::async(std::launch::async,
740 [data = std::move(data),
741 filepath,
742 options]() -> bool {
743 auto writer = IO::ImageWriterRegistry::instance().create_writer(filepath);
744 if (!writer) {
746 "save_image task: no writer registered for '{}'", filepath);
747 return false;
748 }
749 const bool ok = writer->write(filepath, data, options);
750 if (!ok) {
752 "save_image task: writer failed for '{}': {}",
753 filepath, writer->get_last_error());
754 } else {
756 "save_image task: wrote '{}'", filepath);
757 }
758 return ok;
759 });
760
761 std::lock_guard lock(m_save_tasks_mutex);
762 m_save_tasks.push_back(std::move(fut));
763
764 std::erase_if(m_save_tasks, [](std::future<bool>& f) {
765 return f.wait_for(std::chrono::seconds(0)) == std::future_status::ready;
766 });
767
768 return true;
769}
770
772{
773 std::vector<std::future<bool>> tasks;
774 {
775 std::lock_guard lock(m_save_tasks_mutex);
776 tasks.swap(m_save_tasks);
777 }
778 for (auto& f : tasks) {
779 f.wait();
780 }
781}
782
783} // namespace MayaFlux::IO
#define MF_INFO(comp, ctx,...)
#define MF_ERROR(comp, ctx,...)
#define MF_TRACE(comp, ctx,...)
#define MF_WARN(comp, ctx,...)
#define MF_DEBUG(comp, ctx,...)
IO::ImageData image
uint32_t id
uint32_t channel
Cycle Behavior: The for_cycles(N) configuration controls how many times the capture operation execute...
void initialize()
Initialize the buffer after construction.
AudioBuffer implementation backed by a StreamContainer.
TextureBuffer implementation backed by a VideoStreamContainer.
static void register_with_registry()
Register this writer with the ImageWriterRegistry.
Definition EXRWriter.cpp:58
static std::string resolve_path(const std::string &filepath)
Resolve a filepath against the project source root if not found as-is.
std::unordered_map< std::shared_ptr< Kakshya::VideoFileContainer >, std::shared_ptr< Kakshya::SoundFileContainer > > m_extracted_audio
std::shared_ptr< Kakshya::VideoFileContainer > load_video(const std::string &filepath)
Load a video file into a VideoFileContainer.
std::unordered_map< std::shared_ptr< Kakshya::CameraContainer >, std::shared_ptr< Buffers::VideoContainerBuffer > > m_camera_buffers
std::unordered_map< uint64_t, std::shared_ptr< CameraReader > > m_camera_readers
std::unordered_map< std::shared_ptr< Kakshya::SoundFileContainer >, std::vector< std::shared_ptr< Buffers::SoundContainerBuffer > > > m_audio_buffers
bool save_image(const std::shared_ptr< Core::VKImage > &image, const std::string &filepath, const IO::ImageWriteOptions &options={})
Save image data to disk asynchronously.
std::shared_ptr< Buffers::TextureBuffer > load_image(const std::string &filepath)
Load an image file into a TextureBuffer.
std::shared_ptr< Kakshya::CameraContainer > open_camera(const CameraConfig &config)
Open a camera device and create a CameraContainer.
std::mutex m_save_tasks_mutex
std::vector< std::shared_ptr< Buffers::SoundContainerBuffer > > hook_audio_container_to_buffers(const std::shared_ptr< Kakshya::SoundFileContainer > &container)
Wire a SoundFileContainer to the audio buffer system.
std::vector< std::future< bool > > m_save_tasks
std::shared_ptr< Nodes::Network::MeshNetwork > load_mesh_network(const std::string &filepath, TextureResolver resolver=nullptr)
Load a 3D model file as a MeshNetwork.
void dispatch_frame_request(uint64_t reader_id)
IOService::request_frame target — shared-lock lookup + pull_frame_all().
std::shared_ptr< Kakshya::DynamicSoundStream > load_audio_bounded(const std::string &filepath, uint64_t max_frames=0, bool truncate=false)
Load an audio file into a fully resident, size-bounded DynamicSoundStream.
void configure_frame_processor(const std::shared_ptr< Kakshya::VideoFileContainer > &container)
std::vector< std::shared_ptr< SoundFileReader > > m_audio_readers
std::vector< std::shared_ptr< Buffers::SoundContainerBuffer > > get_audio_buffers(const std::shared_ptr< Kakshya::SoundFileContainer > &container) const
Retrieve the SoundContainerBuffers created for a container.
std::shared_mutex m_camera_mutex
std::vector< std::shared_ptr< Buffers::MeshBuffer > > load_mesh(const std::string &filepath, TextureResolver resolver=nullptr)
Load all meshes from a 3D model file into MeshBuffer instances.
std::shared_ptr< Buffers::VideoContainerBuffer > hook_video_container_to_buffer(const std::shared_ptr< Kakshya::VideoFileContainer > &container)
Wire a VideoFileContainer to the graphics buffer system.
void configure_audio_processor(const std::shared_ptr< Kakshya::SoundFileContainer > &container)
std::shared_ptr< Kakshya::SoundFileContainer > get_extracted_audio(const std::shared_ptr< Kakshya::VideoFileContainer > &container) const
Retrieve the SoundFileContainer extracted from a video file.
std::shared_ptr< Buffers::VideoContainerBuffer > get_video_buffer(const std::shared_ptr< Kakshya::VideoFileContainer > &container) const
Retrieve the VideoContainerBuffer created for a container.
std::shared_ptr< Buffers::VideoContainerBuffer > get_camera_buffer(const std::shared_ptr< Kakshya::CameraContainer > &container) const
Retrieve the VideoContainerBuffer created for a camera container.
void release_video_reader(uint64_t reader_id)
Release ownership of the reader identified by reader_id.
void dispatch_decode_request(uint64_t reader_id)
IOService::request_decode target — shared-lock lookup + signal_decode().
std::shared_mutex m_buffers_mutex
uint64_t register_video_reader(std::shared_ptr< VideoFileReader > reader)
Assign a globally unique reader_id and take ownership of a reader.
void wait_for_pending_saves()
Wait for all in-flight save operations to complete.
std::shared_ptr< Buffers::VideoContainerBuffer > hook_camera_to_buffer(const std::shared_ptr< Kakshya::CameraContainer > &container)
Wire a CameraContainer to the graphics buffer system.
~IOManager()
Unregisters IOService, releases all owned readers, clears stored buffers.
Definition IOManager.cpp:76
std::shared_ptr< Buffers::BufferManager > m_buffer_manager
std::atomic< uint64_t > m_next_reader_id
IOManager(uint64_t sample_rate, uint32_t buffer_size, uint32_t frame_rate, const std::shared_ptr< Buffers::BufferManager > &buffer_manager)
Construct IOManager and register the IOService into BackendRegistry.
Definition IOManager.cpp:50
std::vector< std::shared_ptr< ImageReader > > m_image_readers
std::shared_ptr< Registry::Service::IOService > m_io_service
std::shared_mutex m_readers_mutex
std::unordered_map< uint64_t, std::shared_ptr< VideoFileReader > > m_video_readers
std::shared_ptr< Kakshya::SoundFileContainer > load_audio(const std::string &filepath, LoadConfig config={})
Load an audio file into a SoundFileContainer.
std::unordered_map< std::shared_ptr< Kakshya::VideoFileContainer >, std::shared_ptr< Buffers::VideoContainerBuffer > > m_video_buffers
static std::shared_ptr< Core::VKImage > load_texture(const std::string &path)
Load image directly into GPU texture (static utility)
std::unique_ptr< ImageWriter > create_writer(const std::string &filepath) const
static ImageWriterRegistry & instance()
static void register_with_registry()
Register this writer with the ImageWriterRegistry.
void register_service(ServiceFactory factory)
Register a backend service capability.
static BackendRegistry & instance()
Get the global registry instance.
void unregister_service()
Unregister a service.
@ AUDIO_BACKEND
Standard audio processing backend configuration.
@ GRAPHICS_BACKEND
Standard graphics processing backend configuration.
std::function< std::shared_ptr< Core::VKImage >(const std::string &path)> TextureResolver
Callable that maps a raw material texture path to a GPU image.
Definition Creator.hpp:17
std::optional< ImageData > download_image(const std::shared_ptr< Core::VKImage > &image)
Download pixel data from a GPU-resident VKImage into host ImageData.
@ ContainerProcessing
Container operations (Kakshya - file/stream/region processing)
@ BufferManagement
Buffer Management (Buffers::BufferManager, creating buffers)
@ FileIO
Filesystem I/O operations.
@ Init
Engine/subsystem initialization.
@ AsyncIO
Async I/O operations ( network, streaming)
@ Runtime
General runtime operations (default fallback)
@ Core
Core engine, backend, subsystems.
@ IO
Networking, file handling, streaming.
@ API
MayaFlux/API Wrapper and convenience functions.
@ ROW_MAJOR
C/C++ style (last dimension varies fastest)
std::string device_name
Platform device string.
Platform-specific FFmpeg input format string for camera devices.
Raw image data loaded from file.
Configuration for image writing.
FileReadOptions file_options
Definition IOManager.hpp:45
AudioReadOptions audio_options
Definition IOManager.hpp:46
VideoReadOptions video_options
Definition IOManager.hpp:47
std::shared_ptr< Kakshya::SoundFileContainer > audio
Definition IOManager.hpp:62
std::shared_ptr< Kakshya::VideoFileContainer > video
Definition IOManager.hpp:61
Result of load_video() when audio extraction is requested via VideoReadOptions::EXTRACT_AUDIO.
Definition IOManager.hpp:60
std::function< void(uint64_t reader_id)> request_frame
Request the identified camera reader to pull the next frame.
Definition IOService.hpp:44
Backend IO streaming service interface.
Definition IOService.hpp:18