Commit 6ebf0634 authored by Thiago Santini's avatar Thiago Santini

Refactors DataRecorder

parent 9c41bfeb
...@@ -10,10 +10,8 @@ DataRecorder::DataRecorder(QString id, QString header, QObject* parent) ...@@ -10,10 +10,8 @@ DataRecorder::DataRecorder(QString id, QString header, QObject* parent)
, dataFile(nullptr) , dataFile(nullptr)
, dataStream(nullptr) , dataStream(nullptr)
, videoWriter(nullptr) , videoWriter(nullptr)
, framerate(0) , framerate(30) // if the fps doesn't get specified, defaults to 30
, firstFrame(true)
, recording(false) , recording(false)
, videoIdx(1)
{ {
if (!id.contains("Journal")) if (!id.contains("Journal"))
pmIdx = gPerformanceMonitor.enrol(id, "Data Recorder"); pmIdx = gPerformanceMonitor.enrol(id, "Data Recorder");
...@@ -40,10 +38,7 @@ void DataRecorder::startRecording() ...@@ -40,10 +38,7 @@ void DataRecorder::startRecording()
void DataRecorder::startRecording(double fps) void DataRecorder::startRecording(double fps)
{ {
videoWriter = std::make_unique<VideoWriter>();
firstFrame = true;
framerate = fps; framerate = fps;
videoIdx = 1;
startRecording(); startRecording();
} }
...@@ -68,24 +63,37 @@ void DataRecorder::stopRecording() ...@@ -68,24 +63,37 @@ void DataRecorder::stopRecording()
} }
} }
template <typename T>
bool DataRecorder::shouldStore(const T& data)
{
return recording && (!gPerformanceMonitor.shouldDrop(pmIdx, data.timestamp, 2000));
}
void DataRecorder::newData(EyeData eyeData) void DataRecorder::newData(EyeData eyeData)
{ {
storeData(eyeData); if (!shouldStore(eyeData))
return;
storeSerializableData(eyeData);
storeVideoData(eyeData);
} }
void DataRecorder::newData(FieldData fieldData) void DataRecorder::newData(FieldData fieldData)
{ {
storeData(fieldData); if (!shouldStore(fieldData))
return;
storeSerializableData(fieldData);
storeVideoData(fieldData);
} }
void DataRecorder::newData(DataTuple dataTuple) void DataRecorder::newData(DataTuple dataTuple)
{ {
// Note that the Journal data recorder isn't registered with the // since we don't store frames here, just check for recording status
// performance monitor since it's cheap to store its data. if (!recording)
if (dataStream && dataStream->status() == QTextStream::Ok) { return;
*dataStream << dataTuple.toQString();
*dataStream << Token::Newline; storeSerializableData(dataTuple);
}
} }
bool DataRecorder::splitVideoFile() bool DataRecorder::splitVideoFile()
...@@ -97,42 +105,42 @@ bool DataRecorder::splitVideoFile() ...@@ -97,42 +105,42 @@ bool DataRecorder::splitVideoFile()
return false; return false;
} }
template <class T> void DataRecorder::initializeVideoWriter(int width, int height, bool color)
void DataRecorder::storeData(T& data)
{ {
videoWriter = std::make_unique<VideoWriter>();
if (!recording) // todo: migrate to ffmpeg or libav
return; QString fileName = id + ".mp4";
if (firstFrame && videoWriter) {
firstFrame = false;
// todo: migrate to ffmpeg or libav auto fourcc = [](const char str[4]) { return VideoWriter::fourcc(str[0], str[1], str[2], str[3]); };
QString fileName = id + ".mp4"; int codec = fourcc("jpeg"); // Uncompressed; Motion JPEG Video
//int codec = fourcc("xvid"); // Compressed; MPEG-4 Video
//int codec = fourcc("divx"); // Compressed; MPEG-4 Video
auto fourcc = [](const char str[4]) { return VideoWriter::fourcc(str[0], str[1], str[2], str[3]); }; if (videoWriter->isOpened())
int codec = fourcc("jpeg"); // Uncompressed; Motion JPEG Video videoWriter->release();
//int codec = fourcc("xvid"); // Compressed; MPEG-4 Video
//int codec = fourcc("divx"); // Compressed; MPEG-4 Video
if (videoWriter->isOpened()) if (!videoWriter->open(fileName.toStdString(), codec, framerate, { width, height }, color))
videoWriter->release(); qWarning() << "Recording failure." << QString("Could not open %1").arg(fileName);
if (!videoWriter->open(fileName.toStdString(), codec, framerate, Size(data.input.cols, data.input.rows), data.input.channels() == 1 ? false : true)) currentVideoFileInfo.setFile(fileName);
qWarning() << "Recording failure." << QString("Could not open %1").arg(fileName); }
currentVideoFileInfo.setFile(fileName); template <typename T>
void DataRecorder::storeSerializableData(const T& data)
{
if (dataStream && dataStream->status() == QTextStream::Ok)
*dataStream << data.toQString() << Token::Newline;
// TODO: add recording timestamp?
}
videoIdx++; template <typename T>
} void DataRecorder::storeVideoData(const T& data)
{
if (gPerformanceMonitor.shouldDrop(pmIdx, data.timestamp, 2000)) if (!videoWriter)
return; initializeVideoWriter(data.input.cols, data.input.rows, data.input.channels() == 1 ? false : true);
if (videoWriter && videoWriter->isOpened()) if (videoWriter->isOpened())
*videoWriter << data.input; *videoWriter << data.input;
if (dataStream && dataStream->status() == QTextStream::Ok)
*dataStream << data.toQString() << Token::Newline;
// TODO: add recording timestamp?
} }
...@@ -38,16 +38,23 @@ private: ...@@ -38,16 +38,23 @@ private:
std::unique_ptr<cv::VideoWriter> videoWriter; std::unique_ptr<cv::VideoWriter> videoWriter;
double framerate; double framerate;
QFileInfo currentVideoFileInfo; QFileInfo currentVideoFileInfo;
bool firstFrame;
std::atomic_bool recording; std::atomic_bool recording;
int videoIdx;
template <class T> template <typename T>
void storeData(T& data); bool shouldStore(const T& data);
template <typename T>
void storeVideoData(const T& data);
template <typename T>
void storeSerializableData(const T& data);
bool splitVideoFile(); bool splitVideoFile();
double fps; double fps;
unsigned int pmIdx; unsigned int pmIdx;
void initializeVideoWriter(int width, int height, bool color);
}; };
class DataRecorderThread : public QObject { class DataRecorderThread : public QObject {
......
Markdown is supported
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