HoviTron Video Pipeline
raytrixdll-v5/RaytrixStreamer.h
1/* ----------------------
2* Copyright 2023 Université Libre de Bruxelles(ULB), Universidad Politécnica de Madrid(UPM), CREAL, Deutsches Zentrum für Luft - und Raumfahrt(DLR)
3
4* Licensed under the Apache License, Version 2.0 (the "License");
5* you may not use this file except in compliance with the License.
6* You may obtain a copy of the License at < http://www.apache.org/licenses/LICENSE-2.0%3E
7
8* Unless required by applicable law or agreed to in writing, software
9* distributed under the License is distributed on an "AS IS" BASIS,
10* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
11* See the License for the specific language governing permissionsand
12* limitations under the License.
13---------------------- */
14
15
16#pragma once
17
18// CREAL - HOVITRON Pipeline header
19#ifdef _WIN32
20#include <filesystem>
21namespace fs = std::filesystem;
22#include <Windows.h>
23#define HVT_ENTRY_ATTR __declspec(dllexport)
24#else
25#include <experimental/filesystem>
26namespace fs = std::experimental::filesystem;
27typedef void* HANDLE;
28#endif
29
30#define HVT_FUNCTION_PROTOTYPES
31#include "HvtStreamingAPI.h"
32
33// C/C++ header
34#include <conio.h>
35#include <iostream>
36#include <thread>
37#include <mutex>
38#include <atomic>
39#include <array>
40#include <fstream>
41
42// Raytrix Header
43#include "Rx.Core\RxException.h"
44#include "Rx.FileIO\Rx.FileIO.Image.h"
45#include "Rx.LFR/LightFieldRuntime.h"
46#include "Rx.LFR/CameraServer.h"
47#include "Rx.LFR/CalibrationManager.h"
48#include "Rx.LFR/Cuda.h"
49#include "Rx.LFR/CudaCompute.h"
50#include "Rx.LFR/ImageQueue.h"
51#include "Rx.LFR\RayFileReader.h"
52#include "Rx.Core/EDepthFillAlgo.h"
53#include "Rx.Core/EDepthAlgo.h"
54#include "Rx.Core/EColorMap.h"
55#include "Rx.LFR/RayFileWriter.h"
56#include "Rx.LFR/SeqFileReader.h"
57#include "Rx.LFR/SeqFileWriter.h"
58#include "Rx.Interop.Runtime30/CameraProperties.h"
59
60// Cuda header
61#include <cuda.h>
62#include <cuda_runtime.h>
63
64// RaytrixStreamer header
65#include "types.h"
66#include "KernelCuda.cuh"
67#include "nlohmann/json.hpp"
68
69#ifndef VK_UUID_SIZE
70#define VK_UUID_SIZE 16U
71#endif
72
73enum class HvtHandleType
74{
75 CONTEXT,
76 SEMAPHORE
77};
78
79template <typename OurType, typename HvtHandle, HvtHandleType htype>
80struct Handle
81{
82 Handle() : type(htype) {}
83 static constexpr HvtHandleType staticType = htype;
84
85 static OurType* check(HvtHandle hvtHandle)
86 {
87 Handle* h = reinterpret_cast<Handle*>(hvtHandle);
88 if (h && staticType == h->type)
89 {
90 return static_cast<OurType*>(h);
91 }
92 else
93 {
94 throw HvtResult::HVT_ERROR_INVALID_HANDLE;
95 }
96 }
97
98 static OurType* opt_check(HvtHandle hvtHandle)
99 {
100 if (!hvtHandle)
101 {
102 return nullptr;
103 }
104 return check(hvtHandle);
105 }
106
107 HvtHandle to_handle()
108 {
109 return reinterpret_cast<HvtHandle>(this);
110 }
111
112private:
113 HvtHandleType type;
114};
115
116struct Semaphore : public Handle<Semaphore, HvtSemaphore, HvtHandleType::SEMAPHORE>
117{
118 cudaExternalSemaphore_t sem;
119 bool isValid;
120};
121
122class RaytrixStreamer : public Handle<RaytrixStreamer, HvtStreamingContext, HvtHandleType::CONTEXT>
123{
124public:
125 /*-------------- Constructor/Destructor */
130 RaytrixStreamer(const uint8_t uuid[VK_UUID_SIZE]);
135 /*--------------------------------------*/
136
137 /*---------- Hovitron API C entry points*/
138 void enumerateStreamsParameters(uint32_t* streamsCount, HvtRGBDStreamParameters* parameters) const;
139 void importStreamImages(const HvtStreamImagesExportInfo& exportInfos);
140 void importSemaphore(const HvtSemaphoreExportInfo& exportInfos);
141 void destroySemaphore(Semaphore* sem) const;
142 void startStreaming();
143 void acquireStreamsFrames(const HvtAcquireStreamFramesInfo& infos);
144 void releaseStreamsFrames(Semaphore* waitSem);
145 void stopStreaming();
146 /*--------------------------------------*/
147
148 /*--------- Getter*/
153 float getMaxDepth();
158 float getMinDepth();
170 HvtExtrinsics getRxExtrinsicParams(size_t idxCam);
176 Rx::LFR::CImageQueue& getCamBuffer(size_t idxCam);
177 /*---------------*/
178
179private:
180 static constexpr auto numSlots = 3;
181 using Clock = std::chrono::steady_clock;
182
183 /*---------- Hovitron API structure*/
184 // Structure for an image slot. The image is given to the vulkan handle through the cudaSurfaceObject_t.
185 struct ImageSlot
186 {
187 cudaSurfaceObject_t cuda_ptr_surf;
188 HVT_OPAQUE_HANDLE* vk_handle;
189 int32_t size;
190 };
191 // A stream is a structure that is sent to the Hovitron Pipeline. It gives all necessery information of the camera and the image.
192 struct ReadStream
193 {
194 size_t colorFrameStride;
195 size_t colorFrameSize;
196 size_t depthFrameStride;
197 size_t depthFrameSize;
198
199 HvtProjectionType projectionType;
200 HvtIntrinsics intrinsics;
201 HvtExtrinsics extrinsics;
202
203 HvtImageFormat colorFormat;
204 HvtImageFormat depthFormat;
205
206 int width_color;
207 int height_color;
208 int width_depth;
209 int height_depth;
210 float anear;
211 float afar;
212
213 std::array<ImageSlot, numSlots> colorSlots;
214 std::array<ImageSlot, numSlots> depthSlots;
215 bool importedColor = false;
216 bool importedDepth = false;
217
218 Clock::duration framePeriod;
219 int frameCount = 1;
220 int streamedFrame = -1;
221
227 int frameIndex(Clock::duration time) const;
233 bool nextFrameReady(Clock::duration time) const;
234 };
235 /*---------------------------------*/
236
237 /*-------------- RaytrixStreamer DLL structure*/
238 // Contain all the information about the way the DLL should work.
239 struct infoJSON_t {
240 // Number of cams
241 size_t numCams = 0;
242 //If the DLL should force the use of a specific RGB resolution
243 bool forceRGBResolution = false;
244 //If the DLL should force the use of a specific RGB depth
245 bool forceDepthResolution = false;
246 // Width of the RGB image
247 unsigned int width = 0;
248 // Height of the RGB image
249 unsigned int height = 0;
250 // Width of the Depth image
251 unsigned int widthDepth = 0;
252 // Height of the Depth image
253 unsigned int heightDepth = 0;
254 // The ID of the cameras
255 unsigned int* uIDs = nullptr;
256 // The filename of the compute parameters
257 Rx::CRxString filenameComputeParameters = Rx::CRxString();
258 // True, if we use sequence files
259 bool loadFromRawFile = false;
260 // Path of these seq files
261 Rx::CRxString* filenameRawFiles = nullptr;
262 // True, if a or some specific calibrations is(are) wanted
263 bool specificCal = false;
264 // The ID of the calibrations
265 Rx::CRxString* GUIDsCalib = nullptr;
266 // The exposure of the cameras to set (allow of better and faster depth computation)
267 float* exposureCams = nullptr;
268 // The path of the extrinsic camera parameters
269 std::string extrinsicParamsPath = std::string();
270 };
271 /*--------------------------------------------*/
272
273 /*--------- Hovitron API functions*/
274
282 void streamingLoop();
288 void uploadFrame(size_t streamId, ReadStream& stream);
292 void swapStreamingToPending();
296 void swapPendingToReading();
297 /*--------------------------------*/
298
299 /*------- Init Raytrix DLL functions */
300
304 void readInfoFromJSON();
308 void initRxCams();
313 void findVulkanGPU(const uint8_t uuid[VK_UUID_SIZE]);
317 void initStreamParameters();
321 void initRxCudaCompute();
325 void initRxSDK();
329 void initArrayCuda();
333 void initRxRayFile();
337 void initMutex();
338 /*---------------------------------*/
339
340 /*--------------- RaytrixDLL functions for RGBD acquire and refine tasks*/
341
345 void acquireRGBD();
351 void refineRGBD();
355 void getRGBDFormats();
360 void launchAsyncLoader(bool needToWaitthreadToFinish = false);
365 void asyncLoaderImage();
370 void asyncLoaderImageOneCam(size_t idxCam);
374 void asyncLoaderImageFromSeqFiles();
379 void asyncLoaderImageFromOneSeqFile(size_t idxCam);
380 // A list of mutexex to assure that we do not have race conditions when the buffer image is moved to the CRxImage object.
381 std::mutex* loaderMtxs;
382 // A list of condition variables that wait until the condition is verified.
383 std::condition_variable* loaderCVs;
384 // The list of conditions to block/unblock load of new data.
385 bool* canLoadImgs;
386 // A mutex to assure that we do not have race conditions between the syncrhonization of cameras and the copy of the data in our CUDA arrays.
387 std::mutex syncMtx;
388 // The condition variable that waits until the condition is verified.
389 std::condition_variable syncCV;
390 // The condition to block/unblock the copy of the datas.
391 bool imgsLoaded = false;
392 /*----------------------------------------------------------------------*/
393
394 /*---------- Debug functions*/
395
407 template<typename T> void writeInFileWindow(T* dataCorrect, T* dataDebug, size_t width, size_t height, size_t sizeWindow, int numCam = 0);
412 void debugFloatDepth();
413 /*--------------------------*/
414
415 /*--------- Hovitron API variables*/
416 int vulkanGPU;
417 Semaphore* synthesisSem;
418 std::vector<ReadStream> readStreams;
419 std::atomic_bool running = false;
420 std::thread streamingThread;
421 uint32_t slotReadingIndex = 0;
422 uint32_t slotPendingIndex = 1;
423 uint32_t slotStreamingIndex = 2;
424 std::atomic_bool newDataInPending = false;
425 std::mutex indicesMutex;
426 std::mutex queueMutex;
427 float numFrames = 0.0f;
428 /*--------------------------------*/
429
430 /*----------------- RaytrixStreamer variables*/
431 // CUDA Streams for stream concurrency programming
432 cudaStream_t* cudaStreams;
433 // CUDA Event to synchronize a stream
434 cudaEvent_t* cudaEvents;
435 // All information that the DLL needs
436 infoJSON_t infoJSON;
437 // A list of pointer to camera calibrations
438 Rx::LFR::CCalibration** camCalibrations;
439 // The camera server class that is able to find attached cameras.
440 Rx::LFR::CCameraServer xCamServer;
441 // This is the CUDA compute instances
442 Rx::LFR::CCudaCompute* xCudaComputes;
443 // Two lists of USHORT arrays
444 unsigned short** imgRGB, ** imgDepth;
445 // Two lists of UCHAR/UBYTE arrays (only RGB image should be in UChar)
446 uchar** finalRGB, ** imgUByteRGB;
447 // Three lists of float arrays (only depth image should be in Float)
448 float** finalDepth, ** imgFloatDepth, **prevFinalDepth;
449 // A list of camera buffers
450 Rx::LFR::CImageQueue* camBuffers;
452 const Rx::Interop::Runtime30::Camera::ETriggerMode::ID camCaptureMode = Rx::Interop::Runtime30::Camera::ETriggerMode::Camera_FreeRun;
453 // Set up the image buffer properties
454 const unsigned uBufferSize = 1;
455 // Set up the image buffer properties
456 const bool bOverwrite = true;
457 // List of CRxImage that are used as a tmp image loader (for camera acquired method)
458 Rx::CRxImage* capturedImages;
459 // List of the format of the RGB and depth images
460 Rx::CRxImageFormat* imgFormatRGB, * imgFormatDepth;
461 // A boolean to know if the formats have been already loaded
462 bool isFormatLoaded = false;
463 // A list of CRayImage that are used as a tmp image loader (for Sequence file acquired method)
464 Rx::LFR::CRayImage* rayImages;
465 // A list of sequence files
466 Rx::LFR::CSeqFileReader* seqReaders;
467 // The pitch of the CUDA RGB and depth array, pitch = number of bytes in row <=> IdxFromPitch = pitch / size(T)
468 size_t* pitchInCudaRGB, * pitchInCudaDepth;
469 // List of reference plane position, allows to where where the reference plane has been put from one camera
470 float* referencePlaneToCameraPlane;
471 // Size of raytrix by default
472 size_t widthDefault = 3840, heightDefault = 2160;
473 // Channel of depth in Depth3D array
474 const size_t channelDepth = 2;
475 // Max time to capture imgs between cams (in ??)
476 const double MAX_TIME_BETWEEN_CAMS = 1000.0;
477 // Max time to wait for buffer to be filled (in ms)
478 const int MAX_TIME_WAIT_BUFFER = 1000;
479 // Name of the environment variable allows loading the parameters
480 const char* ENV_NAME = "HVT_RXDLL_PARAMS_PATH";
481 // ID of the images that we want to compute
482 const Rx::LFR::EImage::ID idRGB = Rx::LFR::EImage::TotalFocus_View_Virtual, idDepth = Rx::LFR::EImage::Depth3D_ViewVirtualUndistorted_To_Reference;
483 // ID of he space to compute the total focus
484 const Rx::LF::ESpace::ID idSpaceRGB = Rx::LF::ESpace::View_VirtualUndistorted;
485 // ID of the space to compute the depth 3D
486 const Rx::LF::ESpace::ID idSpaceDepth3D[2] = { idSpaceRGB, Rx::LF::ESpace::Reference};
487 /*-------------------------------------------*/
488
489
490 /*------- Print fps(variables + functions)*/
491 // A string that will be used to display message as the FPS
492 char* printMsg = NULL;
493 // An uint to know where we need to add a new message to the string
494 unsigned int whereToAddMsg;
495 // A fixed size of the string
496 const int SIZE_MSG = 1000;
497 // Time when the first loop began
498 std::chrono::steady_clock::time_point beginAvgStreaming;
499 // Time when the stream has done one loop
500 std::chrono::steady_clock::time_point endStreaming;
507 void addMsgToPrint(const char* title, long long int averageTime, float frameNumber);
511 void resetPrintMsg();
515 void printFPS();
516 /*----------------------------------------*/
517};
HvtIntrinsicsPerspective getRxIntrinsicParams(size_t idxCam)
Get the intrinsic parameters of the camera of ID "idxCam". The intrinsic parameters are found through...
~RaytrixStreamer()
Free all the memories that were allocated during the streaming process.
HvtExtrinsics getRxExtrinsicParams(size_t idxCam)
Get the extrinsic parameters of the camera of ID "idxCam". The extrinsic parameters are found through...
float getMinDepth()
Get the minimum depth.
float getMaxDepth()
Get the maximum depth.
Rx::LFR::CImageQueue & getCamBuffer(size_t idxCam)
Get the camera buffer in the list of camera buffers.
Parameters for query of the current frames infos.
Intrinsics parameters of a perspective projection.
Description of an RGBD stream.
Export info for images of a stream.
Union of possible intrinsics types data.