diff --git a/openVulkanoCpp/AR/ArFrame.cpp b/openVulkanoCpp/AR/ArFrame.cpp index 6940419..c6a1b93 100644 --- a/openVulkanoCpp/AR/ArFrame.cpp +++ b/openVulkanoCpp/AR/ArFrame.cpp @@ -25,9 +25,9 @@ namespace OpenVulkano::AR m_session->GetRecorder().Save(shared_from_this()); } - void ArFrame::SaveToFile(const std::filesystem::path& path, bool downsample) + void ArFrame::SaveToFile(const std::filesystem::path& path, bool downsample, bool includeAux) { - m_session->GetRecorder().SaveToFile(shared_from_this(), path, downsample); + m_session->GetRecorder().SaveToFile(shared_from_this(), path, downsample, includeAux); } const Scene::Texture* ArFrame::GetImageTexture() diff --git a/openVulkanoCpp/AR/ArFrame.hpp b/openVulkanoCpp/AR/ArFrame.hpp index 473c09c..7fcdf1d 100644 --- a/openVulkanoCpp/AR/ArFrame.hpp +++ b/openVulkanoCpp/AR/ArFrame.hpp @@ -182,7 +182,7 @@ namespace OpenVulkano::AR void Save(); - void SaveToFile(const std::filesystem::path& path, bool downsample = false); + void SaveToFile(const std::filesystem::path& path, bool downsample = false, bool includeAux = true); void SetSaved() { m_saved = true; } diff --git a/openVulkanoCpp/AR/ArRecorder.cpp b/openVulkanoCpp/AR/ArRecorder.cpp index 954b93a..fa6b501 100644 --- a/openVulkanoCpp/AR/ArRecorder.cpp +++ b/openVulkanoCpp/AR/ArRecorder.cpp @@ -60,7 +60,7 @@ namespace OpenVulkano::AR else m_asyncProcessor.Close(); } - void ArRecorder::WriteColorImage(ArFrame* arFrame, MultiPartArchiveWriter* colorWriter, const std::filesystem::path* path, bool highRes) const + void ArRecorder::WriteColorImage(ArFrame* arFrame, IArchiveWriter* colorWriter, const std::filesystem::path* path, bool highRes) const { //BlockProfiler profile("Save AR Frame - Image"); std::string fileName = GetFileName(arFrame->GetFrameId(), "jpg"); @@ -141,10 +141,10 @@ namespace OpenVulkano::AR #endif } - void ArRecorder::WriteDepthImage(ArFrame* arFrame, MultiPartArchiveWriter* depthWriter, MultiPartArchiveWriter* confWriter) + void ArRecorder::WriteDepthImage(ArFrame* arFrame, IArchiveWriter* depthWriter, IArchiveWriter* confWriter) { //BlockProfiler profile("Save AR Frame - Depth"); - if (!m_depthWriter || !m_confidenceWriter) return; + if (!depthWriter || !confWriter) return; auto depthImg = arFrame->GetDepthImage(); std::vector> buffers(2); { // TODO handle alternative depth formats!!!! @@ -175,7 +175,7 @@ namespace OpenVulkano::AR } } - void ArRecorder::WriteMetadata(ArFrame* frame, MultiPartArchiveWriter* metaWriter) + void ArRecorder::WriteMetadata(ArFrame* frame, IArchiveWriter* metaWriter) { //BlockProfiler profileMeta("Save AR Frame - Meta"); std::string metaContent = frame->GetFrameMetadata().ToYaml(); @@ -287,9 +287,23 @@ namespace OpenVulkano::AR else Write(frame.get(), true); } - void ArRecorder::SaveToFile(const std::shared_ptr& frame, const std::filesystem::path& path, bool downsample) + void ArRecorder::SaveToFile(const std::shared_ptr& frame, const std::filesystem::path& path, bool downsample, bool includeAux) + { + if (m_settings.asyncRecording) m_asyncProcessor.Queue(frame, path, downsample, includeAux); + else WriteToFile(frame, path, downsample, includeAux); + } + + void ArRecorder::WriteToFile(const std::shared_ptr& frame, const std::filesystem::path& path, bool downsample, bool includeAux) { WriteColorImage(frame.get(), nullptr, &path, !downsample); + if (includeAux) + { + auto fName = path.string(); + fName.replace(fName.size() - 3, 3, "aux"); + ArchiveWriter writer(fName); + WriteMetadata(frame.get(), &writer); + WriteDepthImage(frame.get(), &writer, &writer); + } } void ArRecorder::WriteMetadataFile() @@ -334,6 +348,16 @@ namespace OpenVulkano::AR } newDataAvailable.notify_all(); } + + void ArRecorder::AsyncProcessor::Queue(const Ptr& frame, const std::filesystem::path& path, bool downsample, bool aux) + { + if (requestExit) return; + { + std::unique_lock lock(queueMutex); + toFile.emplace(frame, path, downsample, aux); + } + newDataAvailable.notify_all(); + } void ArRecorder::AsyncProcessor::Handler() { @@ -342,7 +366,16 @@ namespace OpenVulkano::AR std::unique_lock lock(queueMutex); do { - newDataAvailable.wait(lock, [this]{ return !frameQueue.empty() || !highResFrameQueue.empty() || requestExit; }); + if (Empty()) newDataAvailable.wait(lock, [this]{ return !Empty() || requestExit; }); + while(!toFile.empty()) + { + auto request = std::move(toFile.front()); + toFile.pop(); + if (!request.frame) continue; + lock.unlock(); + recorder->WriteToFile(request.frame, request.path, request.downsample, request.addAux); + lock.lock(); + } while(!highResFrameQueue.empty()) { auto frame = std::move(highResFrameQueue.front()); @@ -353,12 +386,13 @@ namespace OpenVulkano::AR lock.lock(); } if (requestExit) break; - while(!frameQueue.empty()) + if(!frameQueue.empty()) { if (frameQueue.size() > 3) { Logger::AR->warn("Falling behind saving frames, skipping ..."); recorder->m_skippedFrames++; + frameQueue.pop(); //while(frameQueue.size() > 3) frameQueue.pop(); } auto frame = std::move(frameQueue.front()); diff --git a/openVulkanoCpp/AR/ArRecorder.hpp b/openVulkanoCpp/AR/ArRecorder.hpp index 692192a..a33d4f2 100644 --- a/openVulkanoCpp/AR/ArRecorder.hpp +++ b/openVulkanoCpp/AR/ArRecorder.hpp @@ -9,6 +9,7 @@ #include "Math/ByteSize.hpp" #include "Base/Event.hpp" #include "Base/Timer.hpp" +#include "Base/Wrapper.hpp" #include #include #include @@ -21,6 +22,7 @@ namespace OpenVulkano { class IEventHandler; + class IArchiveWriter; class MultiPartArchiveWriter; } @@ -58,11 +60,19 @@ namespace OpenVulkano::AR class ArRecorder final { + struct SaveToFileRequest final + { + Ptr frame; + std::filesystem::path path; + bool downsample, addAux; + }; + struct AsyncProcessor final { ArRecorder* recorder; std::thread processingThread; - std::queue> frameQueue, highResFrameQueue; + std::queue> frameQueue, highResFrameQueue; + std::queue toFile; std::mutex queueMutex; std::condition_variable newDataAvailable; std::atomic_bool requestExit{}; @@ -70,8 +80,10 @@ namespace OpenVulkano::AR explicit AsyncProcessor(ArRecorder* recorder); ~AsyncProcessor(); void Close(); - void Queue(const std::shared_ptr& frame, bool highRes); + void Queue(const Ptr& frame, bool highRes); + void Queue(const Ptr& frame, const std::filesystem::path& path, bool downsample, bool aux); void Handler(); + bool Empty() { return frameQueue.empty() && highResFrameQueue.empty() && toFile.empty(); } }; ArSession* m_session; @@ -87,9 +99,10 @@ namespace OpenVulkano::AR AsyncProcessor m_asyncProcessor; void Write(ArFrame* frame, bool highRes = false); - void WriteMetadata(ArFrame* frame, MultiPartArchiveWriter* metaWriter); - void WriteColorImage(ArFrame* arFrame, MultiPartArchiveWriter* colorWriter, const std::filesystem::path* path, bool highRes) const; - void WriteDepthImage(ArFrame *arFrame, MultiPartArchiveWriter* depthWriter, MultiPartArchiveWriter* confWriter); + void WriteMetadata(ArFrame* frame, IArchiveWriter* metaWriter); + void WriteColorImage(ArFrame* arFrame, IArchiveWriter* colorWriter, const std::filesystem::path* path, bool highRes) const; + void WriteDepthImage(ArFrame *arFrame, IArchiveWriter* depthWriter, IArchiveWriter* confWriter); + void WriteToFile(const std::shared_ptr& frame, const std::filesystem::path& path, bool downsample, bool saveAux); void SplitWriters(); void WriteMetadataFile(); @@ -103,7 +116,7 @@ namespace OpenVulkano::AR void SaveHighResolution(const std::shared_ptr& frame); - void SaveToFile(const std::shared_ptr& frame, const std::filesystem::path& path, bool downsample = false); + void SaveToFile(const std::shared_ptr& frame, const std::filesystem::path& path, bool downsample = false, bool saveAux = true); /** * Starts the recording of the owning AR session