-
Notifications
You must be signed in to change notification settings - Fork 0
Utils
LayerUtils encompasses a collection of helper functions and tools.
Video Recorder manages the overall process of the video recording.
OnFrameEnd function gets called at the end of each frame render cycle. If the recording is active (m_Recording
flag is true), it captures the frame using the CaptureFrames function from the VideoRecorder utility.
void LayerUtils::OnFrameEnd() {
// check if the recording flag is set to true
if(this->m_Recording){
// capture the frames
this->m_VideoRecorder->CaptureFrames();
}
}
StartRecording function initiates the video recording process. Sets the m_Recording
flag to true, enabling the frame capture in OnFrameEnd. It also gets the save path (either default or UI specified path). Initializes the m_VideoRecorder
object with the specified save path. The object then creates the necessary folders.
// create the video recorder object
this->m_VideoRecorder = std::make_unique<AIAC::Utils::VideoRecorder>(savePath);
During screen recording, the utility captures the screen content frame-by-frame using OpenGL to capture the screen's content. It then processes frames using OpenCV and saves each frame as a .jpg file in /frames
folder.
From src/utils/VideoRecorder.h
:
void VideoRecorder::CaptureFrames();
void VideoRecorder::SaveFrames(int height, int width, std::vector<unsigned char> pixels);
StopRecording function stops the video recording process and initiates the processing of the frames and creates the video.
Sets the m_Recording
flag to false, stopping the frame capture in OnFrameEnd. Marks the processing flag m_Processing
as true for UI (so UI displays the status of the video processing).
void LayerUtils::StopRecording(){
AIAC_INFO("Stopped Recording");
// set the recording flag to false
this->m_Recording = false;
// create the video from the frames in a separate thread
std::thread([this]{
this->m_Processing = true;
this->m_VideoRecorder->MakeVideoFromFrames();
// delete the frames folder and video recorder object
this->m_VideoRecorder.reset();
this->m_Processing = false;
}).detach();
};
For the video processing, the VideoRecorder utility gathers all saved frames, sorts them, and uses FFmpeg (at a frame rate of 30 fps, and encoded using the libx264 codec) to create a video file, which is then stored in the /video
folder.
From src/utils/VideoRecorder.h
:
void VideoRecorder::MakeVideoFromFrames();
After the video processing is done, the StopRecording function destroys the m_VideoRecorder
object and sets m_Processing
to false for the UI.
When m_VideoRecorder
object is destroyed it, it also ensures proper cleanup, specifically by deleting the /frames
folder to free up resources.
IsProcessing is used to check the state of the video processing and then it uses it to control the start & stop buttons.
Hole and Toolhead Axis Exporter designed for exporting coordinates of different toolheads and holes. The exported data is written to a file.
ExportCoordinates() function gathers all the functions in one pipeline, it exports both the toolhead and hole axis coordinates (and other information) and writes them from the internal buffer m_Buffer
to a file using WriteBufferToFile().
The ExportToolheadAxis() is responsible for exporting the toolhead information. It first retrieves the active toolhead type from AC_FF_TOOL
macro. In this case, the types are DRILLBIT, CIRCULARSAW, CHAINSAW
.
void HoleToolheadAxisExporter::ExportToolheadAxis(){
ACToolHeadType activeToolheadType = AC_FF_TOOL->GetType();
if (activeToolheadType == ACToolHeadType::DRILLBIT){
auto drillBitData = AC_FF_TOOL->GetData<DrillBitData>();
this->WriteCoordToBuffer("Toolhead", AC_FF_TOOL->GetName(), "ToolbaseGO", drillBitData.ToolbaseGO);
this->WriteCoordToBuffer("Toolhead", AC_FF_TOOL->GetName(), "TooltipGO", drillBitData.TooltipGO);
}
...
For different type of toolhead, we are getting different types of GO points. For drillbit, we export drillBitData.ToolbaseGO
and drillBitData.TooltipGO
. Other GO points that could be retrieved can be found in AIAC/ACInfoToolhead.h
The ExportHoleAxis() is responsible for accessing the hole information.
void HoleToolheadAxisExporter::ExportHoleAxis(){
std::string activeHoleType = AC_FF_COMP->GetTypeString();
if (activeHoleType == "HOLE"){
TimberInfo::Hole* hole = dynamic_cast<TimberInfo::Hole*>(AC_FF_COMP);
if (hole) {
std::string currentComponentID = AIAC_APP.GetLayer<LayerModel>()->GetACInfoModel().GetTimberInfo().GetCurrentComponentID();
this->WriteCoordToBuffer(activeHoleType, currentComponentID, "StartPoint", hole->GetStartPointGO());
this->WriteCoordToBuffer(activeHoleType, currentComponentID, "EndPoint", hole->GetEndPointGO());
}
}
}
Again, we are making sure that it is the hole by checking if AC_FF_COMP
is pointing to an object of type TimberInfo::Hole
. If AC_FF_COMP
is indeed an instance of TimberInfo::Hole or is derived from it, the dynamic_cast will succeed, and the resulting value of the cast will be a valid pointer to that object.
TimberInfo::Hole* hole = dynamic_cast<TimberInfo::Hole*>(AC_FF_COMP);
WriteCoordToBuffer is the function that is called in ExportHoleAxis() and ExportToolheadAxis() to write the information and coordinates to buffer m_Buffer
.
It writes:
void WriteCoordToBuffer(const std::string& itemType, //its a hole/toolhead
std::string itemName, // toolhead/hole current name
const std::string& pointType, // GO point type
std::shared_ptr<GOPoint> goPoint // shared pointer that has X,Y,Z coordinates);
WriteBufferToFile() function exports the information about toolhead/holes to /temp/coordinates.log
file by default. It also writes the current timestamp in the YYYY-MM-DD HH:MM:SS
format and creates the line spacing between each batch of the exports.
SetSaveFolderPath manages the save path where the utils should be saved. In UI, it used in void LayerUI::ShowSaveVideoRecorderFileDialog()
or it just uses the default path from config.ini
void SetSaveFolderPath(std::string path);
There are also functions that are used in LayerUI.cpp
.
The Screenshot
class is intended to take the snap of the current window and the camera buffer which is colored.
Window Screenshot | Buffer Screenshot |
---|---|
For current window snap, LayerUtils.cpp
checks if the m_WindowScreenshot
is true
, if it is, then OnFrameEnd()
calls TakeWindowScreenshot()
which receives the path for screenshot saving and begins to capture the current state of the window, in CaptureWindow()
.
The camera buffer screenshot TakeBufferScreenshot()
in LayerUtils.cpp
receives the saving path, then it calls CaptureBuffer()
that gets the colored camera buffer frame from the GetColorCurrentFrame()
.
void Screenshot::CaptureBuffer() {
cv::Mat currentFrame;
AIAC_APP.GetLayer<AIAC::LayerCamera>()->MainCamera.GetColorCurrentFrame().GetCvMat().copyTo(currentFrame);
All the screenshots are saved in /temp/screenshots
folder by default.
GetSaveFolderPath is used to get the path of the current utils folder, so the VideoRecorder
, HoleToolheadAxisExporter
and Screenshot
could write in this path. It is also used in LayerUI.cpp
to display the path for the user.
std::string GetSaveFolderPath(){return m_UtilsPath;};
IsProcessing is used to check the state of the video processing and then it uses it to control the start & stop buttons.