Add initial AR playback support
This commit is contained in:
54
openVulkanoCpp/AR/Provider/Playback/ArFramePlayback.cpp
Normal file
54
openVulkanoCpp/AR/Provider/Playback/ArFramePlayback.cpp
Normal file
@@ -0,0 +1,54 @@
|
|||||||
|
/*
|
||||||
|
* This Source Code Form is subject to the terms of the Mozilla Public
|
||||||
|
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||||
|
* file, You can obtain one at https://mozilla.org/MPL/2.0/.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include "ArFramePlayback.hpp"
|
||||||
|
#include "ArSessionPlayback.h"
|
||||||
|
#include "Base/BlockProfiler.hpp"
|
||||||
|
|
||||||
|
namespace openVulkanoCpp::AR::Playback
|
||||||
|
{
|
||||||
|
ArFramePlayback::ArFramePlayback(const std::shared_ptr<ArSessionPlayback>& session, ArPlaybackReader& frameReader)
|
||||||
|
: ArFrame(session)
|
||||||
|
{
|
||||||
|
BlockProfiler profile("Read_AR_Frame");
|
||||||
|
const auto data = frameReader.ReadMetadata();
|
||||||
|
frameMetadata = ArFrameMetadata::FromXML(data.Data(), data.Size());
|
||||||
|
colorImgData = frameReader.ReadColorImage();
|
||||||
|
auto depth = frameReader.ReadDepthImage();
|
||||||
|
confImgData = std::move(depth.confidence.image);
|
||||||
|
depthImgData = std::move(depth.depth.image);
|
||||||
|
depthImage.format = session->GetSessionMetadata().depthFormat;
|
||||||
|
depthImage.intrinsic = frameMetadata.intrinsic.GetForResolution({depth.depth.header.width, depth.depth.header.height});
|
||||||
|
depthImage.depth.data = depthImgData.get();
|
||||||
|
depthImage.depth.resolution = { depth.depth.header.width, depth.depth.header.height };
|
||||||
|
depthImage.confidence.data = confImgData.get();
|
||||||
|
depthImage.depth.resolution = { depth.confidence.header.width, depth.confidence.header.height };
|
||||||
|
|
||||||
|
colorImage.intrinsic = frameMetadata.intrinsic.GetForResolution({ colorImgData.cols, colorImgData.rows });
|
||||||
|
colorImage.format = ArImagePlanar::Format::RGB;
|
||||||
|
colorImage.luminescenceOrColor = { colorImgData.data, { colorImgData.cols, colorImgData.rows }};
|
||||||
|
}
|
||||||
|
|
||||||
|
ArImagePlanar ArFramePlayback::GetCameraImage()
|
||||||
|
{
|
||||||
|
return colorImage;
|
||||||
|
}
|
||||||
|
|
||||||
|
ArDepthImage ArFramePlayback::GetDepthImage()
|
||||||
|
{
|
||||||
|
return depthImage;
|
||||||
|
}
|
||||||
|
|
||||||
|
Math::Matrix4f ArFramePlayback::GetCameraViewForCurrentDeviceOrientation()
|
||||||
|
{
|
||||||
|
return Math::Utils::inverse(GetCameraTransformation());
|
||||||
|
}
|
||||||
|
|
||||||
|
Math::Matrix4f ArFramePlayback::GetCameraProjection(Math::Vector2f viewportSize, float near, float far)
|
||||||
|
{
|
||||||
|
return GetFrameMetadata().projection; //TODO
|
||||||
|
}
|
||||||
|
}
|
||||||
60
openVulkanoCpp/AR/Provider/Playback/ArPlaybackReader.cpp
Normal file
60
openVulkanoCpp/AR/Provider/Playback/ArPlaybackReader.cpp
Normal file
@@ -0,0 +1,60 @@
|
|||||||
|
/*
|
||||||
|
* This Source Code Form is subject to the terms of the Mozilla Public
|
||||||
|
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||||
|
* file, You can obtain one at https://mozilla.org/MPL/2.0/.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include "ArPlaybackReader.hpp"
|
||||||
|
|
||||||
|
#if __has_include("turbojpeg.h")
|
||||||
|
#include <turbojpeg.h>
|
||||||
|
|
||||||
|
namespace openVulkanoCpp::AR::Playback
|
||||||
|
{
|
||||||
|
ColorImg ArPlaybackReader::ReadColorImage()
|
||||||
|
{
|
||||||
|
ColorImg img;
|
||||||
|
auto file = m_archiveColor.GetNextFile();
|
||||||
|
|
||||||
|
long unsigned int jpegSize = file->second.Size();
|
||||||
|
unsigned char* compressedImage = reinterpret_cast<uint8_t*>(file->second.Data());
|
||||||
|
|
||||||
|
int jpegSubsamp;
|
||||||
|
tjhandle jpegDecompressor = tjInitDecompress();
|
||||||
|
tjDecompressHeader2(jpegDecompressor, compressedImage, jpegSize, &img.cols, &img.rows, &jpegSubsamp);
|
||||||
|
|
||||||
|
img.channels = 3;
|
||||||
|
img.dataPtr = std::shared_ptr<uint8_t>(new uint8_t[img.cols * img.rows * 3]);
|
||||||
|
img.data = img.dataPtr.get();
|
||||||
|
|
||||||
|
//TODO is it better to not map to rgb? to keep the same pipeline as on device
|
||||||
|
tjDecompress2(jpegDecompressor, compressedImage, jpegSize, img.data, img.cols, 0/*pitch*/, img.rows, TJPF_RGB, TJFLAG_FASTDCT);
|
||||||
|
//tjDecompressToYUV2(jpegDecompressor, compressedImage, jpegSize, img.data, img.cols, img.rows, 1, TJFLAG_FASTDCT);
|
||||||
|
tjDestroy(jpegDecompressor);
|
||||||
|
|
||||||
|
//auto buff = new uint8_t[img.cols * img.rows * 3];
|
||||||
|
|
||||||
|
//YuvUtils::NV12FromChromaPlanes(buff, img.data + (img.cols * img.rows), img.cols * img.rows / 4);
|
||||||
|
|
||||||
|
return img;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#else
|
||||||
|
#define STB_IMAGE_IMPLEMENTATION
|
||||||
|
#include <stb_image.h>
|
||||||
|
|
||||||
|
namespace openVulkanoCpp::AR::Playback
|
||||||
|
{
|
||||||
|
ColorImg ArPlaybackReader::ReadColorImage()
|
||||||
|
{
|
||||||
|
ColorImg img;
|
||||||
|
auto file = m_archiveColor.GetNextFile();
|
||||||
|
img.dataPtr = std::shared_ptr<uint8_t>(
|
||||||
|
stbi_load_from_memory(reinterpret_cast<stbi_uc*>(file->second.Data()), file->second.Size(), &img.cols, &img.rows, &img.channels, 3),
|
||||||
|
&stbi_image_free);
|
||||||
|
img.data = img.dataPtr.get();
|
||||||
|
return img;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
#endif
|
||||||
65
openVulkanoCpp/AR/Provider/Playback/ArPlaybackReader.hpp
Normal file
65
openVulkanoCpp/AR/Provider/Playback/ArPlaybackReader.hpp
Normal file
@@ -0,0 +1,65 @@
|
|||||||
|
/*
|
||||||
|
* This Source Code Form is subject to the terms of the Mozilla Public
|
||||||
|
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||||
|
* file, You can obtain one at https://mozilla.org/MPL/2.0/.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include "IO/Archive/ArchiveReader.hpp"
|
||||||
|
#include "IO/Files/Pfm.hpp"
|
||||||
|
#include "IO/Files/Pnm.hpp"
|
||||||
|
#include <string>
|
||||||
|
#include <fstream>
|
||||||
|
|
||||||
|
namespace openVulkanoCpp::AR::Playback
|
||||||
|
{
|
||||||
|
struct DepthImage
|
||||||
|
{
|
||||||
|
PfmImage depth;
|
||||||
|
PnmImage confidence;
|
||||||
|
};
|
||||||
|
|
||||||
|
struct ColorImg
|
||||||
|
{
|
||||||
|
std::shared_ptr<uint8_t> dataPtr;
|
||||||
|
uint8_t* data;
|
||||||
|
int cols, rows, channels;
|
||||||
|
};
|
||||||
|
|
||||||
|
class ArPlaybackReader final
|
||||||
|
{
|
||||||
|
static constexpr std::string_view TAR_EXTENSIONS_REGEX = R"(\.(tar(\.gz|\.bz2)?|tgz|tbz|tb2|tbz2))";
|
||||||
|
|
||||||
|
ArchiveReader m_archiveMetadata, m_archiveColor, m_archiveDepth, m_archiveConfidence;
|
||||||
|
public:
|
||||||
|
ArPlaybackReader(const std::string& recDir)
|
||||||
|
{
|
||||||
|
std::string extensions = R"((_\d+|\.part\d+)?)" + std::string(TAR_EXTENSIONS_REGEX);
|
||||||
|
m_archiveMetadata.Open(recDir, ".*meta(data)?" + extensions);
|
||||||
|
m_archiveColor.Open(recDir, ".*(color|image)" + extensions);
|
||||||
|
m_archiveDepth.Open(recDir, ".*depth" + extensions);
|
||||||
|
m_archiveConfidence.Open(recDir, ".*conf(idence)?" + extensions);
|
||||||
|
}
|
||||||
|
|
||||||
|
Array<char> ReadMetadata()
|
||||||
|
{
|
||||||
|
return std::move(m_archiveMetadata.GetNextFile()->second);
|
||||||
|
}
|
||||||
|
|
||||||
|
ColorImg ReadColorImage();
|
||||||
|
|
||||||
|
DepthImage ReadDepthImage()
|
||||||
|
{
|
||||||
|
DepthImage img;
|
||||||
|
m_archiveDepth.GetNextFileAsStream([&img](const FileDescription&, std::istream& stream) { img.depth.Read(stream); });
|
||||||
|
m_archiveConfidence.GetNextFileAsStream([&img](const FileDescription&, std::istream& stream) { img.confidence.Read(stream); });
|
||||||
|
return img;
|
||||||
|
}
|
||||||
|
|
||||||
|
[[nodiscard]] bool HasNext() const
|
||||||
|
{
|
||||||
|
return m_archiveMetadata.HasNext() && m_archiveDepth.HasNext() && m_archiveConfidence.HasNext() && m_archiveColor.HasNext();
|
||||||
|
}
|
||||||
|
};
|
||||||
|
}
|
||||||
85
openVulkanoCpp/AR/Provider/Playback/ArSessionPlayback.cpp
Normal file
85
openVulkanoCpp/AR/Provider/Playback/ArSessionPlayback.cpp
Normal file
@@ -0,0 +1,85 @@
|
|||||||
|
/*
|
||||||
|
* This Source Code Form is subject to the terms of the Mozilla Public
|
||||||
|
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||||
|
* file, You can obtain one at https://mozilla.org/MPL/2.0/.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include "ArSessionPlayback.h"
|
||||||
|
#include "ArFramePlayback.hpp"
|
||||||
|
#include "Base/Logger.hpp"
|
||||||
|
#include <filesystem>
|
||||||
|
|
||||||
|
namespace openVulkanoCpp::AR::Playback
|
||||||
|
{
|
||||||
|
ArSessionPlayback::ArSessionPlayback(const std::string& recordingPath, bool autoAdvance)
|
||||||
|
: ArSession(ArSessionMetadata(recordingPath)), recordingPath(recordingPath), autoAdvance(autoAdvance), playbackReader(recordingPath)
|
||||||
|
{
|
||||||
|
capabilities = ArSessionCapabilities(metadata.type, ArSessionType::PLAYBACK, false, metadata.depthFormat != ArDepthFormat::UNAVAILABLE, false);
|
||||||
|
constants = { Math::Matrix4f(1), metadata.confidenceRange };
|
||||||
|
}
|
||||||
|
|
||||||
|
ArSessionPlayback::~ArSessionPlayback() = default;
|
||||||
|
|
||||||
|
void ArSessionPlayback::Start()
|
||||||
|
{
|
||||||
|
running = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
void ArSessionPlayback::Stop()
|
||||||
|
{
|
||||||
|
running = false;
|
||||||
|
}
|
||||||
|
|
||||||
|
void ArSessionPlayback::Pause()
|
||||||
|
{
|
||||||
|
running = false;
|
||||||
|
}
|
||||||
|
|
||||||
|
std::shared_ptr<ArFrame> ArSessionPlayback::GetFrame()
|
||||||
|
{
|
||||||
|
try
|
||||||
|
{
|
||||||
|
if (playbackReader.HasNext())
|
||||||
|
{
|
||||||
|
std::shared_ptr<ArFrame> frame = std::make_shared<ArFramePlayback>(shared_from_this(), playbackReader);
|
||||||
|
//if (lastTimestamp == frame->GetTimestamp()) return nullptr;
|
||||||
|
lastTimestamp = frame->GetTimestamp();
|
||||||
|
|
||||||
|
// Trigger events
|
||||||
|
OnNewFrame(frame);
|
||||||
|
OnNewCameraTransformation(frame->GetCameraTransformation());
|
||||||
|
if (OnNewCameraViewMatrix.HasHandlers())
|
||||||
|
{
|
||||||
|
auto view = frame->GetCameraViewForCurrentDeviceOrientation();
|
||||||
|
OnNewCameraViewMatrix(view);
|
||||||
|
}
|
||||||
|
if (playbackReader.HasNext())
|
||||||
|
{
|
||||||
|
OnNewFrameAvailable();
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
OnSessionInterruptionChange(true);
|
||||||
|
}
|
||||||
|
|
||||||
|
return frame;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
catch (const std::exception& e)
|
||||||
|
{
|
||||||
|
Logger::AR->error("Failed to read AR frame: {}", e.what());
|
||||||
|
}
|
||||||
|
Stop();
|
||||||
|
return nullptr;
|
||||||
|
}
|
||||||
|
|
||||||
|
ArRecorder* ArSessionPlayback::GetRecorder()
|
||||||
|
{
|
||||||
|
return nullptr;
|
||||||
|
}
|
||||||
|
|
||||||
|
ArType ArSessionPlayback::GetArType()
|
||||||
|
{
|
||||||
|
return capabilities.GetArType();
|
||||||
|
}
|
||||||
|
}
|
||||||
42
openVulkanoCpp/AR/Provider/Playback/ArSessionPlayback.h
Normal file
42
openVulkanoCpp/AR/Provider/Playback/ArSessionPlayback.h
Normal file
@@ -0,0 +1,42 @@
|
|||||||
|
/*
|
||||||
|
* This Source Code Form is subject to the terms of the Mozilla Public
|
||||||
|
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||||
|
* file, You can obtain one at https://mozilla.org/MPL/2.0/.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include "AR/ArSession.h"
|
||||||
|
#include "ArPlaybackReader.hpp"
|
||||||
|
#include "Math/Timestamp.hpp"
|
||||||
|
|
||||||
|
namespace openVulkanoCpp::AR::Playback
|
||||||
|
{
|
||||||
|
class ArSessionPlayback final : public ArSession, public std::enable_shared_from_this<ArSessionPlayback>
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
ArSessionPlayback(const std::string& recordingPath, bool autoAdvance);
|
||||||
|
|
||||||
|
~ArSessionPlayback() override;
|
||||||
|
|
||||||
|
void Start() override;
|
||||||
|
|
||||||
|
void Stop() override;
|
||||||
|
|
||||||
|
void Pause() override;
|
||||||
|
|
||||||
|
[[nodiscard]] std::shared_ptr<ArFrame> GetFrame() override;
|
||||||
|
|
||||||
|
[[nodiscard]] ArRecorder* GetRecorder() override;
|
||||||
|
|
||||||
|
[[nodiscard]] ArSessionType GetSessionType() override { return ArSessionType::PLAYBACK; }
|
||||||
|
|
||||||
|
[[nodiscard]] ArType GetArType() override;
|
||||||
|
|
||||||
|
private:
|
||||||
|
Math::Timestamp lastTimestamp;
|
||||||
|
const std::string recordingPath;
|
||||||
|
const bool autoAdvance;
|
||||||
|
ArPlaybackReader playbackReader;
|
||||||
|
};
|
||||||
|
}
|
||||||
Reference in New Issue
Block a user