From 4af5dbd59620617bb6fd4778107c471f2580b6f6 Mon Sep 17 00:00:00 2001 From: Georg Hagen Date: Thu, 4 Jul 2024 09:07:31 +0200 Subject: [PATCH] Add support for saving color images directly to file --- openVulkanoCpp/AR/ArRecorder.cpp | 26 ++++++++++++++----- openVulkanoCpp/AR/ArRecorder.hpp | 13 +++++++--- .../AR/Provider/ArKit/ArFrameArKit.mm | 5 ++++ 3 files changed, 34 insertions(+), 10 deletions(-) diff --git a/openVulkanoCpp/AR/ArRecorder.cpp b/openVulkanoCpp/AR/ArRecorder.cpp index c5a1ebe..336c6a5 100644 --- a/openVulkanoCpp/AR/ArRecorder.cpp +++ b/openVulkanoCpp/AR/ArRecorder.cpp @@ -54,7 +54,7 @@ namespace OpenVulkano::AR ArRecorder::~ArRecorder() = default; - void ArRecorder::WriteColorImage(ArFrame* arFrame, MultiPartArchiveWriter* colorWriter, bool highRes) const + void ArRecorder::WriteColorImage(ArFrame* arFrame, MultiPartArchiveWriter* colorWriter, const std::filesystem::path* path, bool highRes) const { BlockProfiler profile("Save AR Frame - Image"); std::string fileName = GetFileName(arFrame->GetFrameId(), "jpg"); @@ -95,10 +95,19 @@ namespace OpenVulkano::AR uint8_t* outBuffer = nullptr; unsigned long size = 0; - if (tjCompressFromYUVPlanes(handle, buffers, resX, nullptr, resY, TJSAMP_420, &outBuffer, &size, 95, TJFLAG_FASTDCT)) + if (tjCompressFromYUVPlanes(handle, buffers, resX, nullptr, resY, TJSAMP_420, &outBuffer, &size, 95, TJFLAG_FASTDCT)) [[unlikely]] Logger::AR->error("Failed to create JPEG! {}", tjGetErrorStr()); - else - colorWriter->AddFile(fileName.c_str(), outBuffer, size); + else [[likely]] + { + if (colorWriter) [[likely]] + colorWriter->AddFile(fileName.c_str(), outBuffer, size); + if (path) [[unlikely]] + { + std::ofstream outFile(*path, std::ios::binary); + outFile.write(reinterpret_cast(outBuffer), size); + outFile.close(); + } + } tjFree(outBuffer); #endif } @@ -151,7 +160,7 @@ namespace OpenVulkano::AR bool useHighResWriter = highRes && m_settings.highResFramesInSeparateArchive; BlockProfiler profile("Save AR Frame"); WriteMetadata(frame, useHighResWriter ? m_highResWriter.get() : m_metadataWriter.get()); - WriteColorImage(frame, useHighResWriter ? m_highResWriter.get() : m_colorWriter.get(), highRes); + WriteColorImage(frame, useHighResWriter ? m_highResWriter.get() : m_colorWriter.get(), nullptr, highRes); WriteDepthImage(frame, useHighResWriter ? m_highResWriter.get() : m_depthWriter.get(), useHighResWriter ? m_highResWriter.get() : m_confidenceWriter.get()); @@ -230,7 +239,7 @@ namespace OpenVulkano::AR void ArRecorder::SaveHighResolution(const std::shared_ptr& frame) { - if (!m_recording) return; + if (!m_recording || !m_settings.saveHighResFrames) return; if (m_settings.asyncRecording) { m_asyncProcessor.Queue(frame, true); @@ -238,6 +247,11 @@ namespace OpenVulkano::AR else Write(frame.get(), true); } + void ArRecorder::SaveToFile(const std::shared_ptr& frame, const std::filesystem::path& path, bool downsample) + { + WriteColorImage(frame.get(), nullptr, &path, !downsample); + } + //region AsyncProcessor ArRecorder::AsyncProcessor::AsyncProcessor(ArRecorder* recorder) : recorder(recorder), processingThread(&ArRecorder::AsyncProcessor::Handler, this) diff --git a/openVulkanoCpp/AR/ArRecorder.hpp b/openVulkanoCpp/AR/ArRecorder.hpp index 1033ddb..bd02b79 100644 --- a/openVulkanoCpp/AR/ArRecorder.hpp +++ b/openVulkanoCpp/AR/ArRecorder.hpp @@ -50,6 +50,7 @@ namespace OpenVulkano::AR size_t archiveSize = 2_GiB; bool downsampleColor = true; bool highResFramesInSeparateArchive = true; + bool saveHighResFrames = true; bool asyncRecording = true; }; @@ -81,7 +82,7 @@ namespace OpenVulkano::AR void Write(ArFrame* frame, bool highRes = false); void WriteMetadata(ArFrame* frame, MultiPartArchiveWriter* metaWriter); - void WriteColorImage(ArFrame* arFrame, MultiPartArchiveWriter* colorWriter, bool highRes) const; + void WriteColorImage(ArFrame* arFrame, MultiPartArchiveWriter* colorWriter, const std::filesystem::path* path, bool highRes) const; void WriteDepthImage(ArFrame *arFrame, MultiPartArchiveWriter* depthWriter, MultiPartArchiveWriter* confWriter); public: @@ -93,6 +94,8 @@ 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); + /** * Starts the recording of the owning AR session */ @@ -178,12 +181,14 @@ namespace OpenVulkano::AR * Checks if a separate archive is used for the high res frames. * @return true = using the separate archive file; false = using the normal archive files */ - bool GetHighResFramesInSeparateArchive() const { return m_settings.highResFramesInSeparateArchive; } + bool GetHighResFramesInSeparateArchive() const { return m_settings.highResFramesInSeparateArchive; } - void SetArchivePartMaxFileSize(size_t maxPartSize = 2_GiB) { m_settings.archiveSize = maxPartSize; } + void SetArchivePartMaxFileSize(size_t maxPartSize = 2_GiB) { m_settings.archiveSize = maxPartSize; } - size_t GetArchivePartMaxFileSize() const { return m_settings.archiveSize; } + size_t GetArchivePartMaxFileSize() const { return m_settings.archiveSize; } const RecordingSettings& GetRecordingSettings() const { return m_settings; } + + void SetRecordHighResImages(bool recHighRes = true) { m_settings.saveHighResFrames = recHighRes; } }; } diff --git a/openVulkanoCpp/AR/Provider/ArKit/ArFrameArKit.mm b/openVulkanoCpp/AR/Provider/ArKit/ArFrameArKit.mm index de56bc9..ebbd00a 100644 --- a/openVulkanoCpp/AR/Provider/ArKit/ArFrameArKit.mm +++ b/openVulkanoCpp/AR/Provider/ArKit/ArFrameArKit.mm @@ -98,6 +98,11 @@ namespace OpenVulkano::AR::ArKit m_colorImage.format = ArImagePlanar::Format::NV12; m_colorImage.luminescenceOrColor.resolution = GetSize(arKitFrame.capturedImage); m_colorImage.uv.resolution = m_colorImage.luminescenceOrColor.resolution / 2u; +#ifdef DEBUG + assert(m_colorImage.uv.resolution.x == GetSize(arKitFrame.capturedImage, 1).x); + auto format = CVPixelBufferGetPixelFormatType(arKitFrame.capturedImage); + assert(format == kCVPixelFormatType_420YpCbCr8BiPlanarFullRange); +#endif m_depthImage.format = ArDepthFormat::METER_FP32; m_depthImage.depth.resolution = GetDepthSize(arKitFrame);