Commit d0780166 authored by Matteo's avatar Matteo
Browse files

add formatting config and style guide

parent e075f46c
# EditorConfig is awesome: https://EditorConfig.org
# top-most EditorConfig file
root = true
[*]
indent_style = space
indent_size = 4
end_of_line = lf
charset = utf-8
trim_trailing_whitespace = false
insert_final_newline = false
\ No newline at end of file
UNAME := $(shell uname) UNAME := $(shell uname)
FORMATTER = clang-format
DOCS_GEN = doxygen
FORMAT_OPT = -i -style="{BasedOnStyle: google,IndentWidth: 4,ColumnLimit: 120}"
TARGET = video_analyser
ifeq ($(UNAME), Linux) ifeq ($(UNAME), Linux)
OPEN = xdg-open OPEN = xdg-open
...@@ -10,7 +14,7 @@ ifeq ($(UNAME), Windows) ...@@ -10,7 +14,7 @@ ifeq ($(UNAME), Windows)
OPEN = start OPEN = start
endif endif
.PHONY: all clean test docs run .PHONY: all clean test docs run build
build: build:
cmake -S . -B build cmake -S . -B build
...@@ -25,8 +29,11 @@ clean: ...@@ -25,8 +29,11 @@ clean:
rm -rf docs/html rm -rf docs/html
rm -rf docs/latex rm -rf docs/latex
format:
$(FORMATTER) $(FORMAT_OPT) src/*.cpp src/*.h src/lib/*.cpp src/lib/*.h tests/*.cpp
docs: docs:
doxygen docs/Doxyfile && $(OPEN) docs/html/index.html $(DOCS_GEN) docs/Doxyfile && $(OPEN) docs/html/index.html
run: run:
./bin/audio_analyser ./bin/video_analyser
...@@ -44,7 +44,7 @@ Run the project from the root directory: ...@@ -44,7 +44,7 @@ Run the project from the root directory:
make run make run
``` ```
## Documentation ## Generate the documentation
Along with the source code, the documentation of the *Video Analyser* is provided in the `docs` folder. The documentation is generated with [Doxygen](https://www.doxygen.nl/index.html) and can be accessed by opening the `index.html` file in the `docs/html` folder with a browser. Along with the source code, the documentation of the *Video Analyser* is provided in the `docs` folder. The documentation is generated with [Doxygen](https://www.doxygen.nl/index.html) and can be accessed by opening the `index.html` file in the `docs/html` folder with a browser.
To generate the documentation, run the following command from the root folder: To generate the documentation, run the following command from the root folder:
......
# Documentation # Documentation
[TOC]
> There is no worse software than undocumented software. > There is no worse software than undocumented software.
## Style guide ![Meme](../img/meme-documentation.jpg)
## Generate the documentation
Along with the source code, the documentation of the *Video Analyser* is provided in the `docs` folder. The documentation is generated with [Doxygen](https://www.doxygen.nl/index.html) and can be accessed by opening the `index.html` file in the `docs/html` folder with a browser.
To generate the documentation, run the following command from the root folder:
```
make docs
```
Note that Doxygen must be installed on your machine.
## Write the documentation
Doxygen is a tool for generating documentation from annotated C++ sources, as well as other popular programming languages like C, Objective-C, C#, PHP, Java, Python, IDL (Corba, Microsoft, and UNO/OpenOffice flavors), Fortran, VHDL, Tcl, and to some extent D.
To access Doxygen superpowers you need to add comments to your code. Doxygen supports two types of comments: single-line and multi-line comments. Single-line comments start with `///` or `//!` and multi-line comments start with `/**` and end with `*/`. The following example shows how to use both types of comments:
```
/// This is a single-line comment.
//! This is also a single-line comment.
/**
* This is a multi-line comment.
*/
```
A sample of Doxygen commented class looks like this:
```
/**
* @class SampleClass
* @brief This is a sample class.
*
* This class is used to show how to comment a class with Doxygen.
*/
class SampleClass {
private:
int field1; /**< This is a sample field. */
public:
/**
* @brief This is a sample constructor.
*
* This constructor is used to show how to comment a constructor with Doxygen.
*/
SampleClass();
/**
* @brief This is a sample destructor.
*
* This destructor is used to show how to comment a destructor with Doxygen.
*/
~SampleClass();
/**
* @brief This is a sample method.
*
* This method is used to show how to comment a method with Doxygen.
*
* @param[in] param1 This is a sample parameter.
* @param[in] param2 This is another sample parameter.
* @return This is a sample return value.
*/
int sampleMethod(int param1, int param2);
};
```
For more information about Doxygen, please refer to the [official documentation](https://www.doxygen.nl/manual/index.html).
# Style guide
The code is written following C++20 standard, to ensure the best readability and maintainability. The code is formatted using [clang-format](https://clang.llvm.org/docs/ClangFormat.html) with the [Google C++ Style Guide](https://google.github.io/styleguide/cppguide.html) as a reference. The code is written following C++20 standard, to ensure the best readability and maintainability. The code is formatted using [clang-format](https://clang.llvm.org/docs/ClangFormat.html) with the [Google C++ Style Guide](https://google.github.io/styleguide/cppguide.html) as a reference.
To format the code, run the following command from the root folder:
```
make format
```
Note that clang-format must be installed on your machine.
In addition to the Google C++ Style Guide, the following rules are applied:
- when returning multiple values, use `std::tuple` or `std::pair`, instead of passing by reference;
- when dealing with nullable values, use `std::optional`;
- avoid to manipulate global variables, if you need to share data between different parts of the code, use dependency injection and pass the data as a parameter;
\ No newline at end of file
...@@ -65,7 +65,7 @@ docker build -t mpai-video-analyzer . ...@@ -65,7 +65,7 @@ docker build -t mpai-video-analyzer .
To run the container, run the following command: To run the container, run the following command:
``` ```
docker run -it --rm -v /path/to/video/analyser:/app mpai-video-analyzer -v /path/to/your/data:/data /bin/bash docker run -it --rm -v /path/to/video/analyser:/app -v /path/to/your/data:/data /bin/bash mpai-video-analyzer
``` ```
where `/path/to/video/analyser` is the path to the *Video Analyser* folder. where `/path/to/video/analyser` is the path to the *Video Analyser* folder.
...@@ -83,7 +83,6 @@ There are four required parameters of interest: ...@@ -83,7 +83,6 @@ There are four required parameters of interest:
There are also other required parameters which deeply influence the behaviour of the *Video Analyser* and, therefore, ***should not be modified unless with great knowledge of what you are doing***. They are: There are also other required parameters which deeply influence the behaviour of the *Video Analyser* and, therefore, ***should not be modified unless with great knowledge of what you are doing***. They are:
1. `TapeThresholdPercentual` that specifies the minimum percentage of different pixels for considering the current frame under the tape ROI as a potential Irregularity; 1. `TapeThresholdPercentual` that specifies the minimum percentage of different pixels for considering the current frame under the tape ROI as a potential Irregularity;
2. `CapstanThresholdPercentual` that specifies the minimum percentage of different pixels for considering the current frame under the capstan ROI as a potential Irregularity; 2. `CapstanThresholdPercentual` that specifies the minimum percentage of different pixels for considering the current frame under the capstan ROI as a potential Irregularity;
3. `MinDist` that specifies the minimum distance between the centers of the detected objects for the detection of the reading head;
4. `AngleThresh` that specifies the angle votes threshold for the detection of the reading head; 4. `AngleThresh` that specifies the angle votes threshold for the detection of the reading head;
5. `ScaleThresh` that specifies the scale votes threshold for the detection of the reading head; 5. `ScaleThresh` that specifies the scale votes threshold for the detection of the reading head;
6. `PosThresh` that specifies the position votes threshold for the detection of the reading head; 6. `PosThresh` that specifies the position votes threshold for the detection of the reading head;
......
# Software Requirements
The software should be able to, given as input the video of an open reel tape, produce as output two irregularity files where are listed the irregularities found in the video and the irregularities found in the audio.
Irregularity files are JSON files that contain a list of irregularities. Each irregularity is a JSON object that contains structured as follow:
```json
{
"type": "object",
"properties": {
"IrregularityID": {
"type": "string",
"format": "uuid"
},
"Source": {
"enum": ["a", "v", "b"]
},
"TimeLabel": {
"type": "string",
"pattern": "[0-9]{2}:[0-5][0-9]:[0-5][0-9]\\.[0-9]{3}"
},
"IrregularityType": {
"enum": ["sp", "b", "sot", "eot", "da", "di", "m", "s", "wf", "pps", "ssv", "esv", "sb"]
},
"IrregularityProperties": {
"type": "object",
"properties": {
"ReadingSpeedStandard": {
"enum": [0.9375, 1.875, 3.75, 7.5, 15, 30]
},
"ReadingEqualisationStandard": {
"enum": ["IEC", "IEC1", "IEC2"]
},
"WritingSpeedStandard": {
"enum": [0.9375, 1.875, 3.75, 7.5, 15, 30]
},
"WritingEqualisationStandard": {
"enum": ["IEC", "IEC1", "IEC2"]
},
}
},
"ImageURI": {
"type": "string","format": "uri"
},
"AudioFileURI": {
"type": "string",
"format": "uri"
}
}
}
```
\ No newline at end of file
using json = nlohmann::json; using json = nlohmann::json;
void extractIrregularityImagesForAudio(std::string outputPath, const std::string videoPath, json irregularityFileInput, json &irregularityFileOutput2) { void extractIrregularityImagesForAudio(std::string outputPath, const std::string videoPath, json irregularityFileInput,
json &irregularityFileOutput2) {
// Make fromAudioAnalyser folder // Make fromAudioAnalyser folder
int capsDirectory = fs::create_directory(outputPath + "fromAudioAnalyser/"); int capsDirectory = fs::create_directory(outputPath + "fromAudioAnalyser/");
// Open video // Open video
cv::VideoCapture videoCapture(videoPath); cv::VideoCapture videoCapture(videoPath);
// Compute video length in milliseconds // Compute video length in milliseconds
int frameCount = videoCapture.get(CAP_PROP_FRAME_COUNT); int frameCount = videoCapture.get(CAP_PROP_FRAME_COUNT);
int fps = videoCapture.get(CAP_PROP_FPS); int fps = videoCapture.get(CAP_PROP_FPS);
int videoLenghtMS = (frameCount / fps) * 1000 + std::round((float)((frameCount % fps) * 1000) / fps); int videoLenghtMS = (frameCount / fps) * 1000 + std::round((float)((frameCount % fps) * 1000) / fps);
for (int i = 0; i < irregularityFileInput["Irregularities"].size(); i++) { for (int i = 0; i < irregularityFileInput["Irregularities"].size(); i++) {
// Declare output image frame // Declare output image frame
cv::Mat frame; cv::Mat frame;
std::string framePath; std::string framePath;
// Extract TimeLabel from input JSON // Extract TimeLabel from input JSON
std::string timeLabel = irregularityFileInput["Irregularities"][i]["TimeLabel"]; std::string timeLabel = irregularityFileInput["Irregularities"][i]["TimeLabel"];
// Obtain time measures from JSON // Obtain time measures from JSON
int h = stoi(timeLabel.substr(0, 2)); int h = stoi(timeLabel.substr(0, 2));
int min = stoi(timeLabel.substr(3, 2)); int min = stoi(timeLabel.substr(3, 2));
int sec = stoi(timeLabel.substr(6, 2)); int sec = stoi(timeLabel.substr(6, 2));
int ms = stoi(timeLabel.substr(9, 3)); int ms = stoi(timeLabel.substr(9, 3));
std::string safeTimeLabel = timeLabel; std::string safeTimeLabel = timeLabel;
safeTimeLabel[2] = '-'; safeTimeLabel[2] = '-';
safeTimeLabel[5] = '-'; safeTimeLabel[5] = '-';
safeTimeLabel[8] = '-'; safeTimeLabel[8] = '-';
// Compute the Irregularity instant in milliseconds // Compute the Irregularity instant in milliseconds
int irrInstMS = ms + sec*1000 + min*60000 + h*3600000; int irrInstMS = ms + sec * 1000 + min * 60000 + h * 3600000;
// Compute the frame number corresponding to the Irregularity // Compute the frame number corresponding to the Irregularity
int irrFrame = std::round((float)(irrInstMS/1000)*fps); int irrFrame = std::round((float)(irrInstMS / 1000) * fps);
try { try {
framePath = outputPath + "fromAudioAnalyser/AudioIrregularity_" + safeTimeLabel + ".jpg"; framePath = outputPath + "fromAudioAnalyser/AudioIrregularity_" + safeTimeLabel + ".jpg";
videoCapture.set(CAP_PROP_POS_FRAMES, irrFrame); videoCapture.set(CAP_PROP_POS_FRAMES, irrFrame);
videoCapture >> frame; videoCapture >> frame;
cv::imwrite(framePath, frame); cv::imwrite(framePath, frame);
// Append Irregularity information to JSON // Append Irregularity information to JSON
boost::uuids::uuid uuid = boost::uuids::random_generator()(); boost::uuids::uuid uuid = boost::uuids::random_generator()();
irregularityFileOutput2["Irregularities"] += {{ irregularityFileOutput2["Irregularities"] +=
"IrregularityID", irregularityFileInput["Irregularities"][i]["IrregularityID"] {{"IrregularityID", irregularityFileInput["Irregularities"][i]["IrregularityID"]},
}, { {"Source", "a"},
"Source", "a" {"TimeLabel", timeLabel},
}, { {"ImageURI", framePath}};
"TimeLabel", timeLabel } catch (cv::Exception e) {
}, { std::cout << "\033[0;31mTimeLabel error for Audio Analyser Irregularity " << i << "." << std::endl;
"ImageURI", framePath }
} }
};
} catch (cv::Exception e) {
std::cout << "\033[0;31mTimeLabel error for Audio Analyser Irregularity " << i << "." << std::endl;
}
}
} }
\ No newline at end of file
#include "Irregularity.h"
#include <boost/lexical_cast.hpp> #include <boost/lexical_cast.hpp>
#include <boost/uuid/uuid_io.hpp>
#include <boost/uuid/uuid.hpp> #include <boost/uuid/uuid.hpp>
#include <boost/uuid/uuid_generators.hpp> #include <boost/uuid/uuid_generators.hpp>
#include "Irregularity.h" #include <boost/uuid/uuid_io.hpp>
Irregularity::Irregularity(const Irregularity& other) Irregularity::Irregularity(const Irregularity& other)
: id(other.id), source(other.source), time_label(other.time_label), type(other.type) {} : id(other.id), source(other.source), time_label(other.time_label), type(other.type) {}
Irregularity::Irregularity(Irregularity&& other) noexcept Irregularity::Irregularity(Irregularity&& other) noexcept
: id(std::move(other.id)), source(other.source), time_label(std::move(other.time_label)), type(std::move(other.type)) {} : id(std::move(other.id)),
source(other.source),
time_label(std::move(other.time_label)),
type(std::move(other.type)) {}
Irregularity::Irregularity(Source source, string time_label) { Irregularity::Irregularity(Source source, string time_label) {
this->id = boost::uuids::random_generator()(); this->id = boost::uuids::random_generator()();
...@@ -30,14 +34,11 @@ json Irregularity::to_JSON() const { ...@@ -30,14 +34,11 @@ json Irregularity::to_JSON() const {
j["IrregularityID"] = boost::lexical_cast<string>(this->id); j["IrregularityID"] = boost::lexical_cast<string>(this->id);
j["Source"] = sourceToString(this->source); j["Source"] = sourceToString(this->source);
j["TimeLabel"] = this->time_label; j["TimeLabel"] = this->time_label;
if (this->type.has_value()) if (this->type.has_value()) j["IrregularityType"] = irregularityTypeToString(this->type.value());
j["IrregularityType"] = irregularityTypeToString(this->type.value());
if (this->image_URI.has_value()) if (this->image_URI.has_value()) j["ImageURI"] = this->image_URI.value();
j["ImageURI"] = this->image_URI.value();
if (this->audio_URI.has_value()) if (this->audio_URI.has_value()) j["AudioURI"] = this->audio_URI.value();
j["AudioURI"] = this->audio_URI.value();
return j; return j;
} }
...@@ -50,31 +51,19 @@ Irregularity Irregularity::from_JSON(const json& j) { ...@@ -50,31 +51,19 @@ Irregularity Irregularity::from_JSON(const json& j) {
return Irregularity(source, time_label, type); return Irregularity(source, time_label, type);
} }
Source Irregularity::get_source() const { Source Irregularity::get_source() const { return this->source; }
return this->source; string Irregularity::get_time_label() const { return this->time_label; }
} std::optional<IrregularityType> Irregularity::get_type() const { return this->type; }
string Irregularity::get_time_label() const { boost::uuids::uuid Irregularity::get_id() const { return this->id; }
return this->time_label;
}
std::optional<IrregularityType> Irregularity::get_type() const {
return this->type;
}
boost::uuids::uuid Irregularity::get_id() const {
return this->id;
}
std::optional<string> Irregularity::get_audio_URI() const { std::optional<string> Irregularity::get_audio_URI() const { return this->audio_URI; }
return this->audio_URI;
}
Irregularity& Irregularity::set_audio_URI(string audio_URI) { Irregularity& Irregularity::set_audio_URI(string audio_URI) {
this->audio_URI = audio_URI; this->audio_URI = audio_URI;
return *this; return *this;
} }
std::optional<string> Irregularity::get_image_URI() const { std::optional<string> Irregularity::get_image_URI() const { return this->image_URI; }
return this->image_URI;
}
Irregularity& Irregularity::set_image_URI(string image_URI) { Irregularity& Irregularity::set_image_URI(string image_URI) {
this->image_URI = image_URI; this->image_URI = image_URI;
......
...@@ -4,14 +4,15 @@ ...@@ -4,14 +4,15 @@
* @brief Header file containing the Irregularity class * @brief Header file containing the Irregularity class
* @version 1.0 * @version 1.0
* @date 2023-05-14 * @date 2023-05-14
* *
* @copyright Copyright (c) 2023 * @copyright Copyright (c) 2023
* *
*/ */
#ifndef IRREGULARITY_H #ifndef IRREGULARITY_H
#define IRREGULARITY_H #define IRREGULARITY_H
#include <boost/uuid/uuid.hpp> #include <boost/uuid/uuid.hpp>
#include <nlohmann/json.hpp> #include <nlohmann/json.hpp>
#include "enums.h" #include "enums.h"
using std::string; using std::string;
...@@ -20,17 +21,18 @@ using json = nlohmann::json; ...@@ -20,17 +21,18 @@ using json = nlohmann::json;
/** /**
* @class Irregularity * @class Irregularity
* @brief an irregularity of the tape detected by the system * @brief an irregularity of the tape detected by the system
* *
*/ */
class Irregularity { class Irregularity {
private: private:
boost::uuids::uuid id; boost::uuids::uuid id;
Source source; Source source;
string time_label; string time_label;
std::optional<IrregularityType> type; std::optional<IrregularityType> type;
std::optional<string> image_URI; std::optional<string> image_URI;
std::optional<string> audio_URI; std::optional<string> audio_URI;
public:
public:
Irregularity(const Irregularity& other); Irregularity(const Irregularity& other);
Irregularity(Irregularity&& other) noexcept; Irregularity(Irregularity&& other) noexcept;
Irregularity(Source source, string time_label); Irregularity(Source source, string time_label);
...@@ -38,67 +40,67 @@ public: ...@@ -38,67 +40,67 @@ public:
~Irregularity() = default; ~Irregularity() = default;
/** /**
* @brief Convert the Irregularity to a JSON object * @brief Convert the Irregularity to a JSON object
* *
* @return json * @return json
*/ */
json to_JSON() const; json to_JSON() const;
/** /**
* @brief Create an Irregularity object from a JSON object * @brief Create an Irregularity object from a JSON object
* *
* @param j the JSON object * @param j the JSON object
* @return Irregularity * @return Irregularity
*/ */
static Irregularity from_JSON(const json& j); static Irregularity from_JSON(const json& j);
/** /**
* @brief Get the source object * @brief Get the source object
* *
* @return Source * @return Source
*/ */
Source get_source() const; Source get_source() const;
/** /**
* @brief Get the time label object * @brief Get the time label object
* *
* @return string * @return string
*/ */
string get_time_label() const; string get_time_label() const;
/** /**
* @brief Get the type object * @brief Get the type object
* *
* @return IrregularityType * @return IrregularityType
*/ */
std::optional<IrregularityType> get_type() const; std::optional<IrregularityType> get_type() const;
/** /**
* @brief Get the id object * @brief Get the id object
* *
* @return boost::uuids::uuid * @return boost::uuids::uuid
*/ */
boost::uuids::uuid get_id() const; boost::uuids::uuid get_id() const;
/** /**
* @brief Get the audio URI object * @brief Get the audio URI object
* *
* @return std::optional<string> * @return std::optional<string>
*/ */
std::optional<string> get_audio_URI() const; std::optional<string> get_audio_URI() const;
/** /**
* @brief Get the image URI object * @brief Get the image URI object
* *
* @return std::optional<string> * @return std::optional<string>
*/ */
std::optional<string> get_image_URI() const; std::optional<string> get_image_URI() const;
/** /**
* @brief Set the audio URI object * @brief Set the audio URI object
* *
* @param audio_URI * @param audio_URI
* @return Irregularity& * @return Irregularity&
*/ */
Irregularity& set_audio_URI(string audio_URI); Irregularity& set_audio_URI(string audio_URI);
/** /**
* @brief Set the image URI object * @brief Set the image URI object
* *
* @param image_URI * @param image_URI
* @return Irregularity& * @return Irregularity&
*/ */
Irregularity& set_image_URI(string image_URI); Irregularity& set_image_URI(string image_URI);
}; };
#endif // IRREGULARITY_H #endif // IRREGULARITY_H
\ No newline at end of file \ No newline at end of file
#include <exception>
#include "IrregularityFile.h" #include "IrregularityFile.h"
#include <algorithm> #include <algorithm>
#include <exception>
#include <iterator> #include <iterator>
#include <memory> #include <memory>
IrregularityFile::IrregularityFile(std::optional<uint16_t> offset) : offset_(offset) {} IrregularityFile::IrregularityFile(std::optional<uint16_t> offset) : offset_(offset) {}
IrregularityFile::IrregularityFile(const IrregularityFile &rhs) { IrregularityFile::IrregularityFile(const IrregularityFile& rhs) {
std::transform(rhs.irregularities_.begin(), rhs.irregularities_.end(), std::transform(rhs.irregularities_.begin(), rhs.irregularities_.end(), std::back_inserter(irregularities_),
std::back_inserter(irregularities_), [](const std::unique_ptr<Irregularity>& ptr) { return std::make_unique<Irregularity>(*ptr); });
[](const std::unique_ptr<Irregularity> &ptr) {
return std::make_unique<Irregularity>(*ptr);
});
} }
IrregularityFile& IrregularityFile::add(std::unique_ptr<Irregularity> irregularity) { IrregularityFile& IrregularityFile::add(std::unique_ptr<Irregularity> irregularity) {
...@@ -20,9 +18,9 @@ IrregularityFile& IrregularityFile::add(std::unique_ptr<Irregularity> irregulari ...@@ -20,9 +18,9 @@ IrregularityFile& IrregularityFile::add(std::unique_ptr<Irregularity> irregulari
} }
IrregularityFile& IrregularityFile::remove_by_id(const boost::uuids::uuid id) { IrregularityFile& IrregularityFile::remove_by_id(const boost::uuids::uuid id) {
auto it = std::find_if(irregularities_.begin(), irregularities_.end(), [&id](const std::unique_ptr<Irregularity>& irregularity) { auto it =
return irregularity->get_id() == id; std::find_if(irregularities_.begin(), irregularities_.end(),
}); [&id](const std::unique_ptr<Irregularity>& irregularity) { return irregularity->get_id() == id; });
if (it != irregularities_.end()) { if (it != irregularities_.end()) {
irregularities_.erase(it); irregularities_.erase(it);
} }
...@@ -30,23 +28,18 @@ IrregularityFile& IrregularityFile::remove_by_id(const boost::uuids::uuid id) { ...@@ -30,23 +28,18 @@ IrregularityFile& IrregularityFile::remove_by_id(const boost::uuids::uuid id) {
} }
IrregularityFile& IrregularityFile::sort() { IrregularityFile& IrregularityFile::sort() {
std::sort(irregularities_.begin(), irregularities_.end(), [](const std::unique_ptr<Irregularity>& a, const std::unique_ptr<Irregularity>& b) { std::sort(irregularities_.begin(), irregularities_.end(),
return a->get_time_label() < b->get_time_label(); [](const std::unique_ptr<Irregularity>& a, const std::unique_ptr<Irregularity>& b) {
}); return a->get_time_label() < b->get_time_label();
});
return *this; return *this;
} }
std::optional<uint16_t> IrregularityFile::get_offset() const { std::optional<uint16_t> IrregularityFile::get_offset() const { return offset_; }
return offset_;
}
std::vector<std::unique_ptr<Irregularity>>::iterator IrregularityFile::begin() { std::vector<std::unique_ptr<Irregularity>>::iterator IrregularityFile::begin() { return irregularities_.begin(); }
return irregularities_.begin();
}
std::vector<std::unique_ptr<Irregularity>>::iterator IrregularityFile::end() { std::vector<std::unique_ptr<Irregularity>>::iterator IrregularityFile::end() { return irregularities_.end(); }
return irregularities_.end();
}
json IrregularityFile::toJSON() const { json IrregularityFile::toJSON() const {
json j; json j;
......
...@@ -4,90 +4,92 @@ ...@@ -4,90 +4,92 @@
* @brief Header file containing the IrregularityFile class * @brief Header file containing the IrregularityFile class
* @version 1.0 * @version 1.0
* @date 2023-05-14 * @date 2023-05-14
* *
* @copyright Copyright (c) 2023 * @copyright Copyright (c) 2023
* *
*/ */
#ifndef IRREGULARITY_FILE_H #ifndef IRREGULARITY_FILE_H
#define IRREGULARITY_FILE_H #define IRREGULARITY_FILE_H
#include <vector>
#include <nlohmann/json.hpp> #include <nlohmann/json.hpp>
#include "Irregularity.h"
#include <optional> #include <optional>
#include <vector>
#include "Irregularity.h"
using json = nlohmann::json; using json = nlohmann::json;
/** /**
* @class IrregularityFile * @class IrregularityFile
* @brief An IrregularityFile is a collection of Irregularities detected on a tape. * @brief An IrregularityFile is a collection of Irregularities detected on a
* * tape.
*
*/ */
class IrregularityFile { class IrregularityFile {
public: public:
/** /**
* @brief Create an IrregularityFile object from a JSON object * @brief Create an IrregularityFile object from a JSON object
* *
* @param j * @param j
* @return IrregularityFile * @return IrregularityFile
*/ */
static IrregularityFile fromJSON(const json j); static IrregularityFile fromJSON(const json j);
/** /**
* @brief Convert the IrregularityFile to a JSON object * @brief Convert the IrregularityFile to a JSON object
* *
* @return json * @return json
*/ */
json toJSON() const; json toJSON() const;
IrregularityFile(std::optional<uint16_t> offset = std::nullopt); IrregularityFile(std::optional<uint16_t> offset = std::nullopt);
/** /**
* @brief Copy constructor * @brief Copy constructor
* *
* @param rhs * @param rhs
*/ */
IrregularityFile(const IrregularityFile &rhs); IrregularityFile(const IrregularityFile& rhs);
~IrregularityFile() {}; ~IrregularityFile(){};
/** /**
* @brief Add an Irregularity to the IrregularityFile * @brief Add an Irregularity to the IrregularityFile
* *
* @param irregularity * @param irregularity
* @return IrregularityFile& * @return IrregularityFile&
*/ */
IrregularityFile& add(std::unique_ptr<Irregularity> irregularity); IrregularityFile& add(std::unique_ptr<Irregularity> irregularity);
/** /**
* @brief Remove an Irregularity from the IrregularityFile * @brief Remove an Irregularity from the IrregularityFile
* *
* @param id * @param id
* @return IrregularityFile& * @return IrregularityFile&
*/ */
IrregularityFile& remove_by_id(const boost::uuids::uuid id); IrregularityFile& remove_by_id(const boost::uuids::uuid id);
/** /**
* @brief Sort the IrregularityFile by time_label * @brief Sort the IrregularityFile by time_label
* *
* @return IrregularityFile& * @return IrregularityFile&
*/ */
IrregularityFile& sort(); IrregularityFile& sort();
/** /**
* @brief Get the offset object * @brief Get the offset object
* *
* @return std::optional<uint16_t> * @return std::optional<uint16_t>
*/ */
std::optional<uint16_t> get_offset() const; std::optional<uint16_t> get_offset() const;
/** /**
* @brief Get an iterator to the beginning of the IrregularityFile * @brief Get an iterator to the beginning of the IrregularityFile
* *
* @return std::vector<std::unique_ptr<Irregularity>>::iterator * @return std::vector<std::unique_ptr<Irregularity>>::iterator
*/ */
std::vector<std::unique_ptr<Irregularity>>::iterator begin(); std::vector<std::unique_ptr<Irregularity>>::iterator begin();
/** /**
* @brief Get an iterator to the end of the IrregularityFile * @brief Get an iterator to the end of the IrregularityFile
* *
* @return std::vector<std::unique_ptr<Irregularity>>::iterator * @return std::vector<std::unique_ptr<Irregularity>>::iterator
*/ */
std::vector<std::unique_ptr<Irregularity>>::iterator end(); std::vector<std::unique_ptr<Irregularity>>::iterator end();
private: private:
std::optional<uint16_t> offset_; std::optional<uint16_t> offset_;
std::vector<std::unique_ptr<Irregularity>> irregularities_; std::vector<std::unique_ptr<Irregularity>> irregularities_;
}; };
#endif // IRREGULARITY_FILE_HPP #endif // IRREGULARITY_FILE_HPP
#include "TimeLabel.h" #include "TimeLabel.h"
TimeLabel::TimeLabel(/* args */) TimeLabel::TimeLabel(/* args */) {}
{
}
TimeLabel::~TimeLabel() TimeLabel::~TimeLabel() {}
{ \ No newline at end of file
}
\ No newline at end of file
#ifndef TIME_LABEL_H #ifndef TIME_LABEL_H
#define TIME_LABEL_H #define TIME_LABEL_H
class TimeLabel /**
{ * @brief A label that displays the current time in the format hh:mm:ss.mms
private: * @todo Implement this class:
* - Implement the constructor
* - Implement the destructor
* - Move functions from time.h to here
*/
class TimeLabel {
private:
/* data */ /* data */
public: public:
TimeLabel(/* args */); TimeLabel(/* args */);
~TimeLabel(); ~TimeLabel();
}; };
#endif // TIME_LABEL_H #endif // TIME_LABEL_H
\ No newline at end of file \ No newline at end of file
/** /**
* @file colors.h * @file colors.h
* @author Matteo Spanio (dev2@audioinnova.com) * @author Matteo Spanio (dev2@audioinnova.com)
* @brief Header file containing a set of ANSI escape codes to print colored text in the terminal. * @brief Header file containing a set of ANSI escape codes to print colored
* text in the terminal.
*
* When printing text in the terminal, it is possible to use ANSI escape codes
* to change the color of the text. This header file contains a set of
* pre-defined ANSI escape codes to print colored text in the terminal.
*
* @see https://en.wikipedia.org/wiki/ANSI_escape_code
* @version 1.0 * @version 1.0
* @date 2023-05-13 * @date 2023-05-13
*
* @copyright Copyright (c) 2023 * @copyright Copyright (c) 2023
* *
*/ */
#ifndef COLORS_H #ifndef COLORS_H
#define COLORS_H #define COLORS_H
#include <stdlib.h> #include <stdlib.h>
#include <string> #include <string>
using std::string; using std::string;
...@@ -26,4 +33,4 @@ string RED = "\033[91m"; ...@@ -26,4 +33,4 @@ string RED = "\033[91m";
string BOLD = "\033[1m"; string BOLD = "\033[1m";
string UNDERLINE = "\033[4m"; string UNDERLINE = "\033[4m";
string END = "\033[0m"; string END = "\033[0m";
#endif // COLORS_H #endif // COLORS_H
\ No newline at end of file \ No newline at end of file
#include <stdexcept>
#include "enums.h" #include "enums.h"
#include <stdexcept>
std::string sourceToString(Source source) { std::string sourceToString(Source source) {
switch (source) { switch (source) {
case Audio: case Audio:
......
...@@ -4,34 +4,38 @@ ...@@ -4,34 +4,38 @@
* @brief A collection of enums and functions to handle them. * @brief A collection of enums and functions to handle them.
* @version 1.0 * @version 1.0
* @date 2023-05-13 * @date 2023-05-13
* *
* @copyright Copyright (c) 2023 * @copyright Copyright (c) 2023
* *
* This file contains a set of enums to define properties of an Irregularity. * This file contains a set of enums to define properties of an Irregularity.
* The enums are: * The enums are:
* - Source: the source of the Irregularity (Audio, Video or Both) * - Source: the source of the Irregularity (Audio, Video or Both)
* - IrregularityType: the type of Irregularity (Brands on tape, Splice, etc.) that can be present on the tape. * - IrregularityType: the type of Irregularity (Brands on tape, Splice, etc.)
* * that can be present on the tape.
* The file also contains functions to convert from enum to string and viceversa (useful when saving the Irregularity to a file). *
* * The file also contains functions to convert from enum to string and viceversa
* (useful when saving the Irregularity to a file).
*
*/ */
#ifndef ENUMS_H #ifndef ENUMS_H
#define ENUMS_H #define ENUMS_H
#include<string> #include <string>
/** /**
* @enum Source * @enum Source
* @brief The source of the Irregularity (Audio, Video or Both) * @brief The source of the Irregularity (Audio, Video or Both)
* *
* An Irregularity can be detected by the Audio analyser, the Video analyser or both. * An Irregularity can be detected by the Audio analyser, the Video analyser or
* * both.
*
*/ */
enum Source { Audio, Video, Both }; enum Source { Audio, Video, Both };
/** /**
* @enum IrregularityType * @enum IrregularityType
* @brief The type of Irregularity (Brands on tape, Splice, etc.) that can be present on the tape. * @brief The type of Irregularity (Brands on tape, Splice, etc.) that can be
* * present on the tape.
*
* The types of Irregularities are: * The types of Irregularities are:
* - BRANDS_ON_TAPE: Brands on tape * - BRANDS_ON_TAPE: Brands on tape
* - SPLICE: Splice * - SPLICE: Splice
...@@ -47,10 +51,11 @@ enum Source { Audio, Video, Both }; ...@@ -47,10 +51,11 @@ enum Source { Audio, Video, Both };
* - EQUALIZATION: Equalization * - EQUALIZATION: Equalization
* - SPEED_AND_EQUALIZATION: Speed and equalization * - SPEED_AND_EQUALIZATION: Speed and equalization
* - BACKWARD: Backward * - BACKWARD: Backward
* *
* @note Speed, Equalization and Speed and equalization are detected only by the Audio analyser, * @note Speed, Equalization and Speed and equalization are detected only by the
* while the other Irregularities are detected only by the Video analyser. * Audio analyser, while the other Irregularities are detected only by the Video
* * analyser.
*
*/ */
enum IrregularityType { enum IrregularityType {
BRANDS_ON_TAPE, BRANDS_ON_TAPE,
...@@ -73,4 +78,4 @@ std::string sourceToString(Source source); ...@@ -73,4 +78,4 @@ std::string sourceToString(Source source);
Source sourceFromString(std::string source); Source sourceFromString(std::string source);
std::string irregularityTypeToString(IrregularityType type); std::string irregularityTypeToString(IrregularityType type);
IrregularityType irregularityTypeFromString(std::string type); IrregularityType irregularityTypeFromString(std::string type);
#endif // ENUMS_H #endif // ENUMS_H
\ No newline at end of file \ No newline at end of file
#include <iostream>
#include "files.h" #include "files.h"
#include <iostream>
using std::cout, std::endl, std::cerr, std::ofstream, std::ios; using std::cout, std::endl, std::cerr, std::ofstream, std::ios;
void files::saveFile(std::filesystem::path fileName, std::string content, bool append) { void files::saveFile(std::filesystem::path fileName, std::string content, bool append) {
ofstream outputFile; ofstream outputFile;
if (append) { if (append) {
outputFile.open(fileName, ios::app); outputFile.open(fileName, ios::app);
} else { } else {
outputFile.open(fileName); outputFile.open(fileName);
} }
outputFile << content << endl; outputFile << content << endl;
outputFile.close(); outputFile.close();
} }
void files::findFileNameFromPath(std::string* path, std::string* fileName, std::string* extension) { void files::findFileNameFromPath(std::string* path, std::string* fileName, std::string* extension) {
*path = path->substr(path->find_last_of("'") + 1, path->size()); *path = path->substr(path->find_last_of("'") + 1, path->size());
std::string path_without_extension = path->substr(0, path->find_last_of(".")); std::string path_without_extension = path->substr(0, path->find_last_of("."));
*fileName = path_without_extension.substr(path_without_extension.find_last_of("/") + 1, path_without_extension.size()); *fileName =
*extension = path->substr(path->find_last_of(".") + 1, path->size()); path_without_extension.substr(path_without_extension.find_last_of("/") + 1, path_without_extension.size());
*extension = path->substr(path->find_last_of(".") + 1, path->size());
} }
int files::findFileName(std::string videoPath, std::string &fileName, std::string &extension) { int files::findFileName(std::string videoPath, std::string& fileName, std::string& extension) {
files::findFileNameFromPath(&videoPath, &fileName, &extension); files::findFileNameFromPath(&videoPath, &fileName, &extension);
if (extension.compare("avi") != 0 && extension.compare("mp4") != 0 && extension.compare("mov") != 0) { if (extension.compare("avi") != 0 && extension.compare("mp4") != 0 && extension.compare("mov") != 0) {
...@@ -35,4 +36,3 @@ int files::findFileName(std::string videoPath, std::string &fileName, std::strin ...@@ -35,4 +36,3 @@ int files::findFileName(std::string videoPath, std::string &fileName, std::strin
} }
return 0; return 0;
} }
...@@ -4,54 +4,59 @@ ...@@ -4,54 +4,59 @@
* @brief A collection of functions to handle files. * @brief A collection of functions to handle files.
* @version 1.0 * @version 1.0
* @date 2023-05-13 * @date 2023-05-13
* *
* @copyright Copyright (c) 2023 * @copyright Copyright (c) 2023
* *
*/ */
#ifndef FILES_H #ifndef FILES_H
#define FILES_H #define FILES_H
#include <stdlib.h>
#include <filesystem> #include <filesystem>
#include <fstream> #include <fstream>
#include <string>
#include <iostream> #include <iostream>
#include <stdlib.h> #include <string>
/** /**
* @namespace files * @namespace files
* @brief A collection of functions to handle files. * @brief A collection of functions to handle files.
* *
*/ */
namespace files { namespace files {
/** /**
* @fn void saveFile(std::filesystem::path fileName, std::string content, bool append) * @fn void saveFile(std::filesystem::path fileName, std::string content, bool
* @brief Save content to a file * append)
* * @brief Save content to a file
* @param fileName the name of the file *
* @param content the content to be saved * @param fileName the name of the file
* @param append if true, the content will be appended to the file, otherwise the file will be overwritten * @param content the content to be saved
*/ * @param append if true, the content will be appended to the file, otherwise
void saveFile(std::filesystem::path fileName, std::string content, bool append); * the file will be overwritten
*/
void saveFile(std::filesystem::path fileName, std::string content, bool append);
/** /**
* @fn void findFileNameFromPath(std::string* path, std::string* fileName, std::string* extension) * @fn void findFileNameFromPath(std::string* path, std::string* fileName,
* @brief Separates video file name from its extension. * std::string* extension)
* * @brief Separates video file name from its extension.
* @param[in] path Full video path; *
* @param[out] fileName Video file name; * @param[in] path Full video path;
* @param[out] extension Video extension. * @param[out] fileName Video file name;
*/ * @param[out] extension Video extension.
void findFileNameFromPath(std::string* path, std::string* fileName, std::string* extension); */
void findFileNameFromPath(std::string* path, std::string* fileName, std::string* extension);
/** /**
* @fn int findFileName(std::string videoPath, std::string &fileName, std::string &extension) * @fn int findFileName(std::string videoPath, std::string &fileName,
* @brief Check if the specified input video file exists and is supported. * std::string &extension)
* * @brief Check if the specified input video file exists and is supported.
* @param[in] videoPath Full video path; *
* @param[out] fileName Video file name; * @param[in] videoPath Full video path;
* @param[out] extension Video extension. * @param[out] fileName Video file name;
* @return int -1 if the format is not supported, 0 otherwise. * @param[out] extension Video extension.
*/ * @return int -1 if the format is not supported, 0 otherwise.
int findFileName(std::string videoPath, std::string &fileName, std::string &extension); */
} int findFileName(std::string videoPath, std::string& fileName, std::string& extension);
#endif // FILES_H } // namespace files
\ No newline at end of file #endif // FILES_H
\ No newline at end of file
#include "time.h" #include "time.h"
std::string getTimeLabel(int ms, std::string delim) { std::string getTimeLabel(int ms, std::string delim) {
int mil = ms % 1000;
int sec = ms / 1000;
int min = (sec / 60) % 60;
int hours = sec / 3600;
sec = sec % 60;
int mil = ms % 1000; std::string hoursStr = std::to_string(hours), minStr = std::to_string(min), secStr = std::to_string(sec),
int sec = ms / 1000; milStr = std::to_string(mil);
int min = (sec / 60) % 60; if (hours < 10) hoursStr = "0" + hoursStr;
int hours = sec / 3600; if (min < 10) minStr = "0" + minStr;
sec = sec % 60; if (sec < 10) secStr = "0" + secStr;
if (mil < 100) {
std::string hoursStr = std::to_string(hours), minStr = std::to_string(min), secStr = std::to_string(sec), milStr = std::to_string(mil); if (mil < 10) {
if (hours < 10) milStr = "00" + milStr;
hoursStr = "0" + hoursStr; } else {
if (min < 10) milStr = "0" + milStr;
minStr = "0" + minStr; }
if (sec < 10) }
secStr = "0" + secStr;
if (mil < 100) {
if (mil < 10) {
milStr = "00" + milStr;
} else {
milStr = "0" + milStr;
}
}
std::string timeLabel = hoursStr + delim + minStr + delim + secStr + delim + milStr; std::string timeLabel = hoursStr + delim + minStr + delim + secStr + delim + milStr;
return timeLabel; return timeLabel;
} }
Supports Markdown
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment