Autonomy Software C++ 24.5.1
Welcome to the Autonomy Software repository of the Mars Rover Design Team (MRDT) at Missouri University of Science and Technology (Missouri S&T)! API reference contains the source code and other resources for the development of the autonomy software for our Mars rover. The Autonomy Software project aims to compete in the University Rover Challenge (URC) by demonstrating advanced autonomous capabilities and robust navigation algorithms.
Loading...
Searching...
No Matches
RecordingHandler Class Reference

The RecordingHandler class serves to enumerate the cameras available from the CameraHandler and retrieve and write frames from each camera to the filesystem. The recording of each camera can be disabled through constants and the framerate of the recording can be adjusted to save CPU-time and resources. More...

#include <RecordingHandler.h>

Inheritance diagram for RecordingHandler:
Collaboration diagram for RecordingHandler:

Public Types

enum class  RecordingMode { eCameraHandler , eTagDetectionHandler , eObjectDetectionHandler }
 
- Public Types inherited from AutonomyThread< void >
enum  AutonomyThreadState
 

Public Member Functions

 RecordingHandler (RecordingMode eRecordingMode)
 Construct a new Recording Handler:: Recording Handler object.
 
 ~RecordingHandler ()
 Destroy the Recording Handler:: Recording Handler object.
 
void SetRecordingFPS (const int nRecordingFPS)
 Mutator for the desired FPS for all camera recordings.
 
int GetRecordingFPS () const
 Accessor for the desired FPS for all camera recordings.
 
- Public Member Functions inherited from AutonomyThread< void >
 AutonomyThread ()
 Construct a new Autonomy Thread object.
 
virtual ~AutonomyThread ()
 Destroy the Autonomy Thread object. If the parent object or main thread is destroyed or exited while this thread is still running, a race condition will occur. Stopping and joining the thread here insures that the main program can't exit if the user forgot to stop and join the thread.
 
void Start ()
 When this method is called, it starts a new thread that runs the code within the ThreadedContinuousCode method. This is the users main code that will run the important and continuous code for the class.
 
void RequestStop ()
 Signals threads to stop executing user code, terminate. DOES NOT JOIN. This method will not force the thread to exit, if the user code is not written properly and contains WHILE statement or any other long-executing or blocking code, then the thread will not exit until the next iteration.
 
void Join ()
 Waits for thread to finish executing and then closes thread. This method will block the calling code until thread is finished.
 
bool Joinable () const
 Check if the code within the thread and all pools created by it are finished executing and the thread is ready to be closed.
 
AutonomyThreadState GetThreadState () const
 Accessor for the Threads State private member.
 
IPSGetIPS ()
 Accessor for the Frame I P S private member.
 

Private Member Functions

void ThreadedContinuousCode () override
 This code will run continuously in a separate thread. New frames from the cameras that have recording enabled are grabbed and the images are written to the filesystem.
 
void PooledLinearCode () override
 This method holds the code that is ran in the thread pool started by the ThreadedLinearCode() method. It currently does nothing and is not needed in the current implementation of the RecordingHandler.
 
void UpdateRecordableCameras ()
 This method is used internally by the class to update the number of cameras that have recording enabled from the camera handler.
 
void RequestAndWriteCameraFrames ()
 This method is used internally by the RecordingHandler to request and write frames to from the cameras stored in the member variable vectors.
 
void UpdateRecordableTagDetectors ()
 This method is used internally by the class to update the number of TagDetectors that have recording enabled from the camera handler.
 
void RequestAndWriteTagDetectorFrames ()
 This method is used internally by the RecordingHandler to request and write frames to from the TagDetectors stored in the member variable vectors.
 
void UpdateRecordableObjectDetectors ()
 This method is used internally by the class to update the number of ObjectDetectors that have recording enabled from the camera handler.
 
void RequestAndWriteObjectDetectorFrames ()
 This method is used internally by the RecordingHandler to request and write frames to from the ObjectDetectors stored in the member variable vectors.
 

Private Attributes

int m_nTotalVideoFeeds
 
RecordingMode m_eRecordingMode
 
std::vector< std::shared_ptr< ZEDCamera > > m_vZEDCameras
 
std::vector< std::shared_ptr< BasicCamera > > m_vBasicCameras
 
std::vector< std::shared_ptr< TagDetector > > m_vTagDetectors
 
std::vector< std::shared_ptr< ObjectDetector > > m_vObjectDetectors
 
std::vector< cv::VideoWriterm_vCameraWriters
 
std::vector< bool > m_vRecordingToggles
 
std::vector< cv::Matm_vFrames
 
std::vector< cv::cuda::GpuMatm_vGPUFrames
 
std::vector< std::future< bool > > m_vFrameFutures
 

Additional Inherited Members

- Protected Member Functions inherited from AutonomyThread< void >
void RunPool (const unsigned int nNumTasksToQueue, const unsigned int nNumThreads=2, const bool bForceStopCurrentThreads=false)
 When this method is called, it starts/adds tasks to a thread pool that runs nNumTasksToQueue copies of the code within the PooledLinearCode() method using nNumThreads number of threads. This is meant to be used as an internal utility of the child class to further improve parallelization. Default value for nNumThreads is 2.
 
void RunDetachedPool (const unsigned int nNumTasksToQueue, const unsigned int nNumThreads=2, const bool bForceStopCurrentThreads=false)
 When this method is called, it starts a thread pool full of threads that don't return std::futures (like a placeholder for the thread return type). This means the thread will not have a return type and there is no way to determine if the thread has finished other than calling the Join() method. Only use this if you want to 'set and forget'. It will be faster as it doesn't return futures. Runs PooledLinearCode() method code. This is meant to be used as an internal utility of the child class to further improve parallelization.
 
void ParallelizeLoop (const int nNumThreads, const N tTotalIterations, F &&tLoopFunction)
 Given a ref-qualified looping function and an arbitrary number of iterations, this method will divide up the loop and run each section in a thread pool. This function must not return anything. This method will block until the loop has completed.
 
void ClearPoolQueue ()
 Clears any tasks waiting to be ran in the queue, tasks currently running will remain running.
 
void JoinPool ()
 Waits for pool to finish executing tasks. This method will block the calling code until thread is finished.
 
bool PoolJoinable () const
 Check if the internal pool threads are done executing code and the queue is empty.
 
void SetMainThreadIPSLimit (int nMaxIterationsPerSecond=0)
 Mutator for the Main Thread Max I P S private member.
 
int GetPoolNumOfThreads ()
 Accessor for the Pool Num Of Threads private member.
 
int GetPoolQueueLength ()
 Accessor for the Pool Queue Size private member.
 
std::vector< void > GetPoolResults ()
 Accessor for the Pool Results private member. The action of getting results will destroy and remove them from this object. This method blocks if the thread is not finished, so no need to call JoinPool() before getting results.
 
int GetMainThreadMaxIPS () const
 Accessor for the Main Thread Max I P S private member.
 
- Protected Attributes inherited from AutonomyThread< void >
IPS m_IPS
 

Detailed Description

The RecordingHandler class serves to enumerate the cameras available from the CameraHandler and retrieve and write frames from each camera to the filesystem. The recording of each camera can be disabled through constants and the framerate of the recording can be adjusted to save CPU-time and resources.

Author
clayjay3 (clayt.nosp@m.onra.nosp@m.ycowe.nosp@m.n@gm.nosp@m.ail.c.nosp@m.om)
Date
2023-12-26

Member Enumeration Documentation

◆ RecordingMode

enum class RecordingHandler::RecordingMode
strong
44 {
45 eCameraHandler, // Record video feeds from the CameraHandler.
46 eTagDetectionHandler, // Record video feeds from the TagDetectionHandler.
47 eObjectDetectionHandler // Record video feeds from the ObjectDetectionHandler.
48 };

Constructor & Destructor Documentation

◆ RecordingHandler()

RecordingHandler::RecordingHandler ( RecordingMode  eRecordingMode)

Construct a new Recording Handler:: Recording Handler object.

Parameters
eRecordingMode-
Author
clayjay3 (clayt.nosp@m.onra.nosp@m.ycowe.nosp@m.n@gm.nosp@m.ail.c.nosp@m.om)
Date
2024-01-05
30{
31 // Initialize member variables.
32 m_eRecordingMode = eRecordingMode;
33 // Set max FPS of the ThreadedContinuousCode method.
34 this->SetMainThreadIPSLimit(constants::RECORDER_FPS);
35
36 // Resize vectors to match number of video feeds.
37 switch (eRecordingMode)
38 {
39 // RecordingHandler was initialized to record feeds from the CameraHandler.
40 case RecordingMode::eCameraHandler:
41 // Initialize member variables.
42 m_nTotalVideoFeeds = int(CameraHandler::BasicCamName::BASICCAM_END) + int(CameraHandler::ZEDCamName::ZEDCAM_END) - 2;
43 // Resize member vectors to match number of total video feeds to record.
44 m_vZEDCameras.resize(m_nTotalVideoFeeds);
45 m_vBasicCameras.resize(m_nTotalVideoFeeds);
46 m_vCameraWriters.resize(m_nTotalVideoFeeds);
47 m_vRecordingToggles.resize(m_nTotalVideoFeeds);
48 m_vFrames.resize(m_nTotalVideoFeeds);
49 m_vGPUFrames.resize(m_nTotalVideoFeeds);
50 m_vFrameFutures.resize(m_nTotalVideoFeeds);
51 break;
52
53 // RecordingHandler was initialized to record feeds from the TagDetectionHandler.
54 case RecordingMode::eTagDetectionHandler:
55 // Initialize member variables.
56 m_nTotalVideoFeeds = int(TagDetectionHandler::TagDetectors::TAGDETECTOR_END) - 1;
57 // Resize member vectors to match number of total video feeds to record.
58 m_vTagDetectors.resize(m_nTotalVideoFeeds);
59 m_vCameraWriters.resize(m_nTotalVideoFeeds);
60 m_vRecordingToggles.resize(m_nTotalVideoFeeds);
61 m_vFrames.resize(m_nTotalVideoFeeds);
62 m_vFrameFutures.resize(m_nTotalVideoFeeds);
63 break;
64
65 // RecordingHandler was initialized to record feeds from the TagDetectionHandler.
66 case RecordingMode::eObjectDetectionHandler:
67 // Initialize member variables.
68 m_nTotalVideoFeeds = int(ObjectDetectionHandler::ObjectDetectors::OBJECTDETECTOR_END) - 1;
69 // Resize member vectors to match number of total video feeds to record.
70 m_vObjectDetectors.resize(m_nTotalVideoFeeds);
71 m_vCameraWriters.resize(m_nTotalVideoFeeds);
72 m_vRecordingToggles.resize(m_nTotalVideoFeeds);
73 m_vFrames.resize(m_nTotalVideoFeeds);
74 m_vFrameFutures.resize(m_nTotalVideoFeeds);
75 break;
76
77 default:
78 // Do nothing.
79 break;
80 }
81}
void SetMainThreadIPSLimit(int nMaxIterationsPerSecond=0)
Mutator for the Main Thread Max I P S private member.
Definition AutonomyThread.hpp:467
Here is the call graph for this function:

◆ ~RecordingHandler()

RecordingHandler::~RecordingHandler ( )

Destroy the Recording Handler:: Recording Handler object.

Author
clayjay3 (clayt.nosp@m.onra.nosp@m.ycowe.nosp@m.n@gm.nosp@m.ail.c.nosp@m.om)
Date
2023-12-26
91{
92 // Signal and wait for recording thread to stop.
93 this->RequestStop();
94 this->Join();
95
96 // Loop through and close video writers.
97 for (cv::VideoWriter cvCameraWriter : m_vCameraWriters)
98 {
99 // Release video writer.
100 cvCameraWriter.release();
101 }
102}
void Join()
Waits for thread to finish executing and then closes thread. This method will block the calling code ...
Definition AutonomyThread.hpp:180
void RequestStop()
Signals threads to stop executing user code, terminate. DOES NOT JOIN. This method will not force the...
Definition AutonomyThread.hpp:164
Here is the call graph for this function:

Member Function Documentation

◆ SetRecordingFPS()

void RecordingHandler::SetRecordingFPS ( const int  nRecordingFPS)

Mutator for the desired FPS for all camera recordings.

Parameters
nRecordingFPS- The frames per second to record all cameras at.
Author
clayjay3 (clayt.nosp@m.onra.nosp@m.ycowe.nosp@m.n@gm.nosp@m.ail.c.nosp@m.om)
Date
2023-12-26
688{
689 // Set the max iterations per second of the recording handler.
690 this->SetMainThreadIPSLimit(nRecordingFPS);
691}
Here is the call graph for this function:

◆ GetRecordingFPS()

int RecordingHandler::GetRecordingFPS ( ) const

Accessor for the desired FPS for all camera recordings.

Returns
int - The FPS of all camera recordings.
Author
clayjay3 (clayt.nosp@m.onra.nosp@m.ycowe.nosp@m.n@gm.nosp@m.ail.c.nosp@m.om)
Date
2023-12-26
702{
703 // Return member variable value.
704 return this->GetMainThreadMaxIPS();
705}
int GetMainThreadMaxIPS() const
Accessor for the Main Thread Max I P S private member.
Definition AutonomyThread.hpp:531
Here is the call graph for this function:

◆ ThreadedContinuousCode()

void RecordingHandler::ThreadedContinuousCode ( )
overrideprivatevirtual

This code will run continuously in a separate thread. New frames from the cameras that have recording enabled are grabbed and the images are written to the filesystem.

Author
clayjay3 (clayt.nosp@m.onra.nosp@m.ycowe.nosp@m.n@gm.nosp@m.ail.c.nosp@m.om)
Date
2023-12-26

Implements AutonomyThread< void >.

114{
115 // Check what mode recorder was initialized with.
116 switch (m_eRecordingMode)
117 {
118 // Record video feeds from the CameraHandler.
119 case RecordingMode::eCameraHandler:
120 // Update recordable cameras.
122 // Grab and write frames to VideoWriters.
124 break;
125
126 // Record video feeds from the TagDetectionHandler.
127 case RecordingMode::eTagDetectionHandler:
128 // Update recordable detectors.
130 // Grab and write overlay frames to VideoWriters.
132 break;
133
134 // Record video feeds from the ObjectDetectionHandler.
135 case RecordingMode::eObjectDetectionHandler:
136 // Update recordable detectors.
138 // Grab and write overlay frames to VideoWriters.
140 break;
141
142 // Shutdown recording handler.
143 default:
144 // Submit logger message.
145 LOG_ERROR(logging::g_qSharedLogger,
146 "The RecordingHandler was initialized with a RecordingMode enum value that doesn't make sense! Thread is shutting down...");
147 // Request main thread stop.
148 this->RequestStop();
149 break;
150 }
151}
void UpdateRecordableTagDetectors()
This method is used internally by the class to update the number of TagDetectors that have recording ...
Definition RecordingHandler.cpp:436
void UpdateRecordableObjectDetectors()
This method is used internally by the class to update the number of ObjectDetectors that have recordi...
Definition RecordingHandler.cpp:560
void RequestAndWriteTagDetectorFrames()
This method is used internally by the RecordingHandler to request and write frames to from the TagDet...
Definition RecordingHandler.cpp:510
void UpdateRecordableCameras()
This method is used internally by the class to update the number of cameras that have recording enabl...
Definition RecordingHandler.cpp:172
void RequestAndWriteObjectDetectorFrames()
This method is used internally by the RecordingHandler to request and write frames to from the Object...
Definition RecordingHandler.cpp:637
void RequestAndWriteCameraFrames()
This method is used internally by the RecordingHandler to request and write frames to from the camera...
Definition RecordingHandler.cpp:313
Here is the call graph for this function:

◆ PooledLinearCode()

void RecordingHandler::PooledLinearCode ( )
overrideprivatevirtual

This method holds the code that is ran in the thread pool started by the ThreadedLinearCode() method. It currently does nothing and is not needed in the current implementation of the RecordingHandler.

Author
clayjay3 (clayt.nosp@m.onra.nosp@m.ycowe.nosp@m.n@gm.nosp@m.ail.c.nosp@m.om)
Date
2023-12-26

Implements AutonomyThread< void >.

162{}

◆ UpdateRecordableCameras()

void RecordingHandler::UpdateRecordableCameras ( )
private

This method is used internally by the class to update the number of cameras that have recording enabled from the camera handler.

Author
clayjay3 (clayt.nosp@m.onra.nosp@m.ycowe.nosp@m.n@gm.nosp@m.ail.c.nosp@m.om)
Date
2023-12-31
173{
174 // Loop through all Basic cameras from the CameraHandler.
175 for (int nCamera = int(CameraHandler::BasicCamName::BASICCAM_START) + 1; nCamera != int(CameraHandler::BasicCamName::BASICCAM_END); ++nCamera)
176 {
177 // Get pointer to camera.
178 std::shared_ptr<BasicCamera> pBasicCamera = globals::g_pCameraHandler->GetBasicCam(static_cast<CameraHandler::BasicCamName>(nCamera));
179 // Store camera pointer in vector so we can get images later.
180 m_vBasicCameras[nCamera - 1] = pBasicCamera;
181
182 // Check if recording for this camera is enabled.
183 if (pBasicCamera->GetEnableRecordingFlag() && pBasicCamera->GetCameraIsOpen())
184 {
185 // Set recording toggle.
186 m_vRecordingToggles[nCamera - 1] = true;
187 // Setup VideoWriter if needed.
188 if (!m_vCameraWriters[nCamera - 1].isOpened())
189 {
190 // Assemble filepath string.
191 std::filesystem::path szFilePath;
192 std::filesystem::path szFilenameWithExtension;
193 szFilePath = constants::LOGGING_OUTPUT_PATH_ABSOLUTE; // Main location for all recordings.
194 szFilePath += logging::g_szProgramStartTimeString + "/cameras"; // Folder for each program run.
195 szFilenameWithExtension = pBasicCamera->GetCameraLocation() + ".mkv"; // Folder for each camera index or name.
196
197 // Check if directory exists.
198 if (!std::filesystem::exists(szFilePath))
199 {
200 // Create directory.
201 if (!std::filesystem::create_directories(szFilePath))
202 {
203 // Submit logger message.
204 LOG_ERROR(logging::g_qSharedLogger,
205 "Unable to create the VideoWriter output directory: {} for camera {}",
206 szFilePath.string(),
207 pBasicCamera->GetCameraLocation());
208 }
209 }
210
211 // Construct the full output path.
212 std::filesystem::path szFullOutputPath = szFilePath / szFilenameWithExtension;
213
214 // Open writer.
215 bool bWriterOpened = m_vCameraWriters[nCamera - 1].open(szFullOutputPath.string(),
216 cv::VideoWriter::fourcc('H', '2', '6', '4'),
217 constants::RECORDER_FPS,
218 pBasicCamera->GetPropResolution());
219
220 // Check writer opened status.
221 if (!bWriterOpened)
222 {
223 // Submit logger message.
224 LOG_WARNING(logging::g_qSharedLogger,
225 "RecordingHandler: Failed to open cv::VideoWriter for basic camera at path/index {}",
226 pBasicCamera->GetCameraLocation());
227 }
228 }
229 }
230 else
231 {
232 // Set recording toggle.
233 m_vRecordingToggles[nCamera - 1] = false;
234 }
235 }
236
237 // Get index offset so we don't overwrite BasicCam pointers and booleans.
238 int nIndexOffset = int(CameraHandler::BasicCamName::BASICCAM_END) - 2;
239 // Loop through all ZED cameras from the CameraHandler.
240 for (int nCamera = int(CameraHandler::ZEDCamName::ZEDCAM_START) + 1; nCamera != int(CameraHandler::ZEDCamName::ZEDCAM_END); ++nCamera)
241 {
242 // Get pointer to camera.
243 std::shared_ptr<ZEDCamera> pZEDCamera = globals::g_pCameraHandler->GetZED(static_cast<CameraHandler::ZEDCamName>(nCamera));
244 // Store camera pointer in vector so we can get images later.
245 m_vZEDCameras[nCamera + nIndexOffset] = pZEDCamera;
246
247 // Check if recording for this camera is enabled.
248 if (pZEDCamera->GetEnableRecordingFlag() && pZEDCamera->GetCameraIsOpen())
249 {
250 // Set recording toggle.
251 m_vRecordingToggles[nCamera + nIndexOffset] = true;
252 // Setup VideoWriter if needed.
253 if (!m_vCameraWriters[nCamera + nIndexOffset].isOpened())
254 {
255 // Assemble filepath string.
256 std::filesystem::path szFilePath;
257 std::filesystem::path szFilenameWithExtension;
258 szFilePath = constants::LOGGING_OUTPUT_PATH_ABSOLUTE; // Main location for all recordings.
259 szFilePath += logging::g_szProgramStartTimeString + "/cameras"; // Folder for each program run.
260 szFilenameWithExtension =
261 pZEDCamera->GetCameraModel() + "_" + std::to_string(pZEDCamera->GetCameraSerial()) + ".mkv"; // Folder for each camera index or name.
262
263 // Check if directory exists.
264 if (!std::filesystem::exists(szFilePath))
265 {
266 // Create directory.
267 if (!std::filesystem::create_directories(szFilePath))
268 {
269 // Submit logger message.
270 LOG_ERROR(logging::g_qSharedLogger,
271 "Unable to create the output directory: {} for camera {} ({})",
272 szFilePath.string(),
273 pZEDCamera->GetCameraModel(),
274 pZEDCamera->GetCameraSerial());
275 }
276 }
277
278 // Construct the full output path.
279 std::filesystem::path szFullOutputPath = szFilePath / szFilenameWithExtension;
280
281 // Open writer.
282 bool bWriterOpened = m_vCameraWriters[nCamera + nIndexOffset].open(szFullOutputPath,
283 cv::VideoWriter::fourcc('H', '2', '6', '4'),
284 constants::RECORDER_FPS,
285 pZEDCamera->GetPropResolution());
286
287 // Check writer opened status.
288 if (!bWriterOpened)
289 {
290 // Submit logger message.
291 LOG_WARNING(logging::g_qSharedLogger,
292 "RecordingHandler: Failed to open cv::VideoWriter for ZED camera with serial {}",
293 pZEDCamera->GetCameraSerial());
294 }
295 }
296 }
297 else
298 {
299 // Set recording toggle.
300 m_vRecordingToggles[nCamera + nIndexOffset] = false;
301 }
302 }
303}
std::shared_ptr< BasicCamera > GetBasicCam(BasicCamName eCameraName)
Accessor for Basic cameras.
Definition CameraHandler.cpp:189
std::shared_ptr< ZEDCamera > GetZED(ZEDCamName eCameraName)
Accessor for ZED cameras.
Definition CameraHandler.cpp:170
static int fourcc(char c1, char c2, char c3, char c4)
Here is the call graph for this function:
Here is the caller graph for this function:

◆ RequestAndWriteCameraFrames()

void RecordingHandler::RequestAndWriteCameraFrames ( )
private

This method is used internally by the RecordingHandler to request and write frames to from the cameras stored in the member variable vectors.

Author
clayjay3 (clayt.nosp@m.onra.nosp@m.ycowe.nosp@m.n@gm.nosp@m.ail.c.nosp@m.om)
Date
2024-01-01
314{
315 // Loop through total number of cameras and request frames.
316 for (int nIter = 0; nIter < m_nTotalVideoFeeds; ++nIter)
317 {
318 // Check if recording for the camera at this index is enabled.
319 if (m_vRecordingToggles[nIter])
320 {
321 // Check if the camera at the current index is a BasicCam or ZEDCam.
322 if (m_vBasicCameras[nIter] != nullptr)
323 {
324 // Request frame.
325 m_vFrameFutures[nIter] = m_vBasicCameras[nIter]->RequestFrameCopy(m_vFrames[nIter]);
326 }
327 else if (m_vZEDCameras[nIter] != nullptr)
328 {
329 // Check if the camera is setup to use CPU or GPU mats.
330 if (m_vZEDCameras[nIter]->GetUsingGPUMem())
331 {
332 // Grab frames from camera.
333 m_vFrameFutures[nIter] = m_vZEDCameras[nIter]->RequestFrameCopy(m_vGPUFrames[nIter]);
334 }
335 else
336 {
337 // Grab frames from camera.
338 m_vFrameFutures[nIter] = m_vZEDCameras[nIter]->RequestFrameCopy(m_vFrames[nIter]);
339 }
340 }
341 }
342 }
343
344 // Loop through cameras and wait for frame requests to be fulfilled.
345 for (int nIter = 0; nIter < m_nTotalVideoFeeds; ++nIter)
346 {
347 // Check if recording for the camera at this index is enabled.
348 if (m_vRecordingToggles[nIter])
349 {
350 // Check if the camera at the current index is a BasicCam or ZEDCam.
351 if (m_vBasicCameras[nIter] != nullptr)
352 {
353 // Wait for future to be fulfilled.
354 if (m_vFrameFutures[nIter].get() && !m_vFrames[nIter].empty())
355 {
356 // Check if this is a grayscale or color image.
357 if (m_vFrames[nIter].channels() == 1)
358 {
359 // Convert frame from 1 channel grayscale to 3 channel BGR.
360 cv::cvtColor(m_vFrames[nIter], m_vFrames[nIter], cv::COLOR_GRAY2BGR);
361 }
362 // Check if this has an alpha channel.
363 else if (m_vFrames[nIter].channels() == 4)
364 {
365 // Convert from from 4 channels to 3 channels.
366 cv::cvtColor(m_vFrames[nIter], m_vFrames[nIter], cv::COLOR_BGRA2BGR);
367 }
368
369 // Write frame to OpenCV video writer.
370 m_vCameraWriters[nIter].write(m_vFrames[nIter]);
371 }
372 }
373 else if (m_vZEDCameras[nIter] != nullptr)
374 {
375 // Check if the camera is setup to use CPU or GPU mats.
376 if (m_vZEDCameras[nIter]->GetUsingGPUMem())
377 {
378 // Wait for future to be fulfilled.
379 if (m_vFrameFutures[nIter].get() && !m_vGPUFrames[nIter].empty())
380 {
381 // Download GPU mat frame to normal mat.
382 m_vGPUFrames[nIter].download(m_vFrames[nIter]);
383
384 // Check if this is a grayscale or color image.
385 if (m_vFrames[nIter].channels() == 1)
386 {
387 // Convert frame from 1 channel grayscale to 3 channel BGR.
388 cv::cvtColor(m_vFrames[nIter], m_vFrames[nIter], cv::COLOR_GRAY2BGR);
389 }
390 // Check if this has an alpha channel.
391 else if (m_vFrames[nIter].channels() == 4)
392 {
393 // Convert from from 4 channels to 3 channels.
394 cv::cvtColor(m_vFrames[nIter], m_vFrames[nIter], cv::COLOR_BGRA2BGR);
395 }
396
397 // Write frame to OpenCV video writer.
398 m_vCameraWriters[nIter].write(m_vFrames[nIter]);
399 }
400 }
401 else
402 {
403 // Wait for future to be fulfilled.
404 if (m_vFrameFutures[nIter].get() && !m_vFrames[nIter].empty())
405 {
406 // Check if this is a grayscale or color image.
407 if (m_vFrames[nIter].channels() == 1)
408 {
409 // Convert frame from 1 channel grayscale to 3 channel BGR.
410 cv::cvtColor(m_vFrames[nIter], m_vFrames[nIter], cv::COLOR_GRAY2BGR);
411 }
412 // Check if this has an alpha channel.
413 else if (m_vFrames[nIter].channels() == 4)
414 {
415 // Convert from from 4 channels to 3 channels.
416 cv::cvtColor(m_vFrames[nIter], m_vFrames[nIter], cv::COLOR_BGRA2BGR);
417 }
418
419 // Write frame to OpenCV video writer.
420 m_vCameraWriters[nIter].write(m_vFrames[nIter]);
421 }
422 }
423 }
424 }
425 }
426}
__host__ cudaTextureObject_t get() const noexcept
void cvtColor(InputArray src, OutputArray dst, int code, int dstCn=0)
COLOR_BGRA2BGR
COLOR_GRAY2BGR
Here is the call graph for this function:
Here is the caller graph for this function:

◆ UpdateRecordableTagDetectors()

void RecordingHandler::UpdateRecordableTagDetectors ( )
private

This method is used internally by the class to update the number of TagDetectors that have recording enabled from the camera handler.

Author
clayjay3 (clayt.nosp@m.onra.nosp@m.ycowe.nosp@m.n@gm.nosp@m.ail.c.nosp@m.om)
Date
2023-12-31
437{
438 // Loop through all Basic cameras from the CameraHandler.
439 for (int nDetector = int(TagDetectionHandler::TagDetectors::TAGDETECTOR_START) + 1; nDetector != int(TagDetectionHandler::TagDetectors::TAGDETECTOR_END); ++nDetector)
440 {
441 // Get pointer to camera.
442 std::shared_ptr<TagDetector> pTagDetector = globals::g_pTagDetectionHandler->GetTagDetector(static_cast<TagDetectionHandler::TagDetectors>(nDetector));
443 // Store camera pointer in vector so we can get images later.
444 m_vTagDetectors[nDetector - 1] = pTagDetector;
445
446 // Check if recording for this camera is enabled.
447 if (pTagDetector->GetEnableRecordingFlag() && pTagDetector->GetIsReady())
448 {
449 // Set recording toggle.
450 m_vRecordingToggles[nDetector - 1] = true;
451 // Setup VideoWriter if needed.
452 if (!m_vCameraWriters[nDetector - 1].isOpened())
453 {
454 // Assemble filepath string.
455 std::filesystem::path szFilePath;
456 std::filesystem::path szFilenameWithExtension;
457 szFilePath = constants::LOGGING_OUTPUT_PATH_ABSOLUTE; // Main location for all recordings.
458 szFilePath += logging::g_szProgramStartTimeString + "/tagdetector"; // Folder for each program run.
459 szFilenameWithExtension = pTagDetector->GetCameraName() + ".mkv"; // Folder for each camera index or name.
460
461 // Check if directory exists.
462 if (!std::filesystem::exists(szFilePath))
463 {
464 // Create directory.
465 if (!std::filesystem::create_directories(szFilePath))
466 {
467 // Submit logger message.
468 LOG_ERROR(logging::g_qSharedLogger,
469 "Unable to create the VideoWriter output directory: {} for tag detector {}",
470 szFilePath.string(),
471 pTagDetector->GetCameraName());
472 }
473 }
474
475 // Construct the full output path.
476 std::filesystem::path szFullOutputPath = szFilePath / szFilenameWithExtension;
477
478 // Open writer.
479 bool bWriterOpened = m_vCameraWriters[nDetector - 1].open(szFullOutputPath.string(),
480 cv::VideoWriter::fourcc('H', '2', '6', '4'),
481 constants::RECORDER_FPS,
482 pTagDetector->GetProcessFrameResolution());
483
484 // Check writer opened status.
485 if (!bWriterOpened)
486 {
487 // Submit logger message.
488 LOG_WARNING(logging::g_qSharedLogger,
489 "RecordingHandler: Failed to open cv::VideoWriter for tag detector using camera {}",
490 pTagDetector->GetCameraName());
491 }
492 }
493 }
494 else
495 {
496 // Set recording toggle.
497 m_vRecordingToggles[nDetector - 1] = false;
498 }
499 }
500}
std::shared_ptr< TagDetector > GetTagDetector(TagDetectors eDetectorName)
Accessor for TagDetector detectors.
Definition TagDetectionHandler.cpp:132
Here is the call graph for this function:
Here is the caller graph for this function:

◆ RequestAndWriteTagDetectorFrames()

void RecordingHandler::RequestAndWriteTagDetectorFrames ( )
private

This method is used internally by the RecordingHandler to request and write frames to from the TagDetectors stored in the member variable vectors.

Author
clayjay3 (clayt.nosp@m.onra.nosp@m.ycowe.nosp@m.n@gm.nosp@m.ail.c.nosp@m.om)
Date
2024-01-01
511{
512 // Loop through total number of cameras and request frames.
513 for (int nIter = 0; nIter < m_nTotalVideoFeeds; ++nIter)
514 {
515 // Check if recording for the camera at this index is enabled and tag detector at index is not null.
516 if (m_vRecordingToggles[nIter] && m_vTagDetectors[nIter] != nullptr)
517 {
518 // Request frame.
519 m_vFrameFutures[nIter] = m_vTagDetectors[nIter]->RequestDetectionOverlayFrame(m_vFrames[nIter]);
520 }
521 }
522
523 // Loop through cameras and wait for frame requests to be fulfilled.
524 for (int nIter = 0; nIter < m_nTotalVideoFeeds; ++nIter)
525 {
526 // Check if recording for the camera at this index is enabled and tag detector is not null.
527 if (m_vRecordingToggles[nIter] && m_vTagDetectors[nIter] != nullptr)
528 {
529 // Wait for future to be fulfilled.
530 if (m_vFrameFutures[nIter].get() && !m_vFrames[nIter].empty())
531 {
532 // Check if this is a grayscale or color image.
533 if (m_vFrames[nIter].channels() == 1)
534 {
535 // Convert frame from 1 channel grayscale to 3 channel BGR.
536 cv::cvtColor(m_vFrames[nIter], m_vFrames[nIter], cv::COLOR_GRAY2BGR);
537 }
538 // Check if this has an alpha channel.
539 else if (m_vFrames[nIter].channels() == 4)
540 {
541 // Convert from from 4 channels to 3 channels.
542 cv::cvtColor(m_vFrames[nIter], m_vFrames[nIter], cv::COLOR_BGRA2BGR);
543 }
544
545 // Write frame to OpenCV video writer.
546 m_vCameraWriters[nIter].write(m_vFrames[nIter]);
547 }
548 }
549 }
550}
Here is the call graph for this function:
Here is the caller graph for this function:

◆ UpdateRecordableObjectDetectors()

void RecordingHandler::UpdateRecordableObjectDetectors ( )
private

This method is used internally by the class to update the number of ObjectDetectors that have recording enabled from the camera handler.

Author
clayjay3 (clayt.nosp@m.onra.nosp@m.ycowe.nosp@m.n@gm.nosp@m.ail.c.nosp@m.om)
Date
2023-12-31
561{
562 // Loop through all Basic cameras from the CameraHandler.
563 for (int nDetector = int(ObjectDetectionHandler::ObjectDetectors::OBJECTDETECTOR_START) + 1;
564 nDetector != int(ObjectDetectionHandler::ObjectDetectors::OBJECTDETECTOR_END);
565 ++nDetector)
566 {
567 // Get pointer to camera.
568 std::shared_ptr<ObjectDetector> pObjectDetector =
569 globals::g_pObjectDetectionHandler->GetObjectDetector(static_cast<ObjectDetectionHandler::ObjectDetectors>(nDetector));
570 // Store camera pointer in vector so we can get images later.
571 m_vObjectDetectors[nDetector - 1] = pObjectDetector;
572
573 // Check if recording for this camera is enabled.
574 if (pObjectDetector->GetEnableRecordingFlag() && pObjectDetector->GetIsReady())
575 {
576 // Set recording toggle.
577 m_vRecordingToggles[nDetector - 1] = true;
578 // Setup VideoWriter if needed.
579 if (!m_vCameraWriters[nDetector - 1].isOpened())
580 {
581 // Assemble filepath string.
582 std::filesystem::path szFilePath;
583 std::filesystem::path szFilenameWithExtension;
584 szFilePath = constants::LOGGING_OUTPUT_PATH_ABSOLUTE; // Main location for all recordings.
585 szFilePath += logging::g_szProgramStartTimeString + "/objectdetector"; // Folder for each program run.
586 szFilenameWithExtension = pObjectDetector->GetCameraName() + ".mkv"; // Folder for each camera index or name.
587
588 // Check if directory exists.
589 if (!std::filesystem::exists(szFilePath))
590 {
591 // Create directory.
592 if (!std::filesystem::create_directories(szFilePath))
593 {
594 // Submit logger message.
595 LOG_ERROR(logging::g_qSharedLogger,
596 "Unable to create the VideoWriter output directory: {} for tag detector {}",
597 szFilePath.string(),
598 pObjectDetector->GetCameraName());
599 }
600 }
601
602 // Construct the full output path.
603 std::filesystem::path szFullOutputPath = szFilePath / szFilenameWithExtension;
604
605 // Open writer.
606 bool bWriterOpened = m_vCameraWriters[nDetector - 1].open(szFullOutputPath.string(),
607 cv::VideoWriter::fourcc('H', '2', '6', '4'),
608 constants::RECORDER_FPS,
609 pObjectDetector->GetProcessFrameResolution());
610
611 // Check writer opened status.
612 if (!bWriterOpened)
613 {
614 // Submit logger message.
615 LOG_WARNING(logging::g_qSharedLogger,
616 "RecordingHandler: Failed to open cv::VideoWriter for tag detector using camera {}",
617 pObjectDetector->GetCameraName());
618 }
619 }
620 }
621 else
622 {
623 // Set recording toggle.
624 m_vRecordingToggles[nDetector - 1] = false;
625 }
626 }
627}
std::shared_ptr< ObjectDetector > GetObjectDetector(ObjectDetectors eDetectorName)
Accessor for ObjectDetector detectors.
Definition ObjectDetectionHandler.cpp:127
Here is the call graph for this function:
Here is the caller graph for this function:

◆ RequestAndWriteObjectDetectorFrames()

void RecordingHandler::RequestAndWriteObjectDetectorFrames ( )
private

This method is used internally by the RecordingHandler to request and write frames to from the ObjectDetectors stored in the member variable vectors.

Author
clayjay3 (clayt.nosp@m.onra.nosp@m.ycowe.nosp@m.n@gm.nosp@m.ail.c.nosp@m.om)
Date
2024-01-01
638{
639 // Loop through total number of cameras and request frames.
640 for (int nIter = 0; nIter < m_nTotalVideoFeeds; ++nIter)
641 {
642 // Check if recording for the camera at this index is enabled and tag detector at index is not null.
643 if (m_vRecordingToggles[nIter] && m_vObjectDetectors[nIter] != nullptr)
644 {
645 // Request frame.
646 m_vFrameFutures[nIter] = m_vObjectDetectors[nIter]->RequestDetectionOverlayFrame(m_vFrames[nIter]);
647 }
648 }
649
650 // Loop through cameras and wait for frame requests to be fulfilled.
651 for (int nIter = 0; nIter < m_nTotalVideoFeeds; ++nIter)
652 {
653 // Check if recording for the camera at this index is enabled and tag detector is not null.
654 if (m_vRecordingToggles[nIter] && m_vObjectDetectors[nIter] != nullptr)
655 {
656 // Wait for future to be fulfilled.
657 if (m_vFrameFutures[nIter].get() && !m_vFrames[nIter].empty())
658 {
659 // Check if this is a grayscale or color image.
660 if (m_vFrames[nIter].channels() == 1)
661 {
662 // Convert frame from 1 channel grayscale to 3 channel BGR.
663 cv::cvtColor(m_vFrames[nIter], m_vFrames[nIter], cv::COLOR_GRAY2BGR);
664 }
665 // Check if this has an alpha channel.
666 else if (m_vFrames[nIter].channels() == 4)
667 {
668 // Convert from from 4 channels to 3 channels.
669 cv::cvtColor(m_vFrames[nIter], m_vFrames[nIter], cv::COLOR_BGRA2BGR);
670 }
671
672 // Write frame to OpenCV video writer.
673 m_vCameraWriters[nIter].write(m_vFrames[nIter]);
674 }
675 }
676 }
677}
Here is the call graph for this function:
Here is the caller graph for this function:

The documentation for this class was generated from the following files: