Commit 0e465cdb authored by Thiago Santini's avatar Thiago Santini

Starts Performance Monitor Widget

parent 6ad85d0d
......@@ -34,7 +34,9 @@ SOURCES +=\
$${TOP}/src/DataRecorder.cpp \
$${TOP}/src/NetworkStream.cpp \
$${TOP}/src/Reference.cpp \
$${TOP}/src/LogWidget.cpp
$${TOP}/src/LogWidget.cpp \
$${TOP}/src/PerformanceMonitor.cpp \
$${TOP}/src/PerformanceMonitorWidget.cpp
HEADERS += \
$${TOP}/src/MainWindow.h\
......@@ -58,13 +60,16 @@ HEADERS += \
$${TOP}/src/DataRecorder.h \
$${TOP}/src/NetworkStream.h \
$${TOP}/src/Reference.h \
$${TOP}/src/LogWidget.h
$${TOP}/src/LogWidget.h \
$${TOP}/src/PerformanceMonitor.h \
$${TOP}/src/PerformanceMonitorWidget.h
FORMS += \
$${TOP}/src/MainWindow.ui \
$${TOP}/src/CameraWidget.ui \
$${TOP}/src/GazeEstimationWidget.ui \
src/LogWidget.ui
$${TOP}/src/LogWidget.ui \
$${TOP}/src/PerformanceMonitorWidget.ui
RESOURCES += \
$${TOP}/resources.qrc
......
......@@ -7,5 +7,6 @@
<file>icons/EyeRecToo.png</file>
<file>icons/gazeEstimationWidget.png</file>
<file>icons/logWidget.png</file>
<file>icons/performanceMonitorWidget.png</file>
</qresource>
</RCC>
......@@ -37,6 +37,11 @@ CameraWidget::CameraWidget(QString id, ImageProcessor::Type type, QWidget *paren
break;
}
// Early enrollment of stages so they are listed in order :-)
gPerformanceMonitor.enrol(id, "Frame Grabber");
gPerformanceMonitor.enrol(id, "Image Processor");
gPerformanceMonitor.enrol(id, "Data Recorder");
setWindowTitle(id + " Widget");
camera = NULL;
imageProcessor = NULL;
......
......@@ -2,8 +2,8 @@
using namespace cv;
DataRecorder::DataRecorder(QString prefix, QString header, QObject *parent)
: prefix(prefix),
DataRecorder::DataRecorder(QString id, QString header, QObject *parent)
: id(id),
header(header),
videoWriter(NULL),
dataFile(NULL),
......@@ -11,6 +11,8 @@ DataRecorder::DataRecorder(QString prefix, QString header, QObject *parent)
framerate(0),
QObject(parent)
{
if (!id.contains("Journal"))
pmIdx = gPerformanceMonitor.enrol(id, "Data Recorder");
}
DataRecorder::~DataRecorder()
......@@ -20,7 +22,7 @@ DataRecorder::~DataRecorder()
void DataRecorder::startRecording()
{
QString fileName = prefix + "Data.csv";
QString fileName = id + "Data.csv";
dataFile = new QFile( fileName );
if ( !dataFile->open(QIODevice::WriteOnly) ) {
qWarning() << "Recording failure." << QString("Could not open %1").arg(fileName);
......@@ -69,6 +71,9 @@ void DataRecorder::newData(FieldData fieldData)
void DataRecorder::newData(DataTuple dataTuple)
{
// Note that the Journal data recorder doesn't registered with the
// performance monitor since it's cheap to store its data.
if (dataStream == NULL)
return;
......@@ -96,7 +101,7 @@ void DataRecorder::storeData(T &data)
if (firstFrame || splitVideoFile()) {
firstFrame = false;
QString fileName = prefix + "-P" + QString::number(videoIdx) + ".avi";
QString fileName = id + "-P" + QString::number(videoIdx) + ".avi";
int codec = videoWriter->fourcc('D', 'I', 'V', 'X');
if (gHasOpenH264)
......@@ -116,6 +121,9 @@ void DataRecorder::storeData(T &data)
if (!gRecording)
return;
if ( gPerformanceMonitor.shouldDrop(pmIdx, gTimer.elapsed() - data.timestamp, 1000) )
return;
if (videoWriter->isOpened())
*videoWriter << data.input;
if (dataStream->status() == QTextStream::Ok)
......
......@@ -16,7 +16,7 @@ class DataRecorder : public QObject
{
Q_OBJECT
public:
explicit DataRecorder(QString prefix, QString header, QObject *parent = 0);
explicit DataRecorder(QString id, QString header, QObject *parent = 0);
~DataRecorder();
signals:
......@@ -30,7 +30,7 @@ public slots:
void newData(DataTuple dataTuple);
private:
QString prefix;
QString id;
QString header;
QFile *dataFile;
QTextStream *dataStream;
......@@ -44,14 +44,16 @@ private:
void storeData(T &data);
bool splitVideoFile();
double fps;
unsigned int pmIdx;
};
class DataRecorderThread : public QObject
{
Q_OBJECT
public:
explicit DataRecorderThread(QString prefix, QString header, QObject *parent = 0)
: prefix(prefix),
explicit DataRecorderThread(QString id, QString header, QObject *parent = 0)
: id(id),
header(header),
dataRecorder(NULL),
QObject(parent)
......@@ -76,7 +78,7 @@ signals:
public slots:
void create() {
dataRecorder = new DataRecorder(prefix, header, this);
dataRecorder = new DataRecorder(id, header, this);
connect(this, SIGNAL(startRecording(double)),
dataRecorder, SLOT(startRecording(double)) );
connect(this, SIGNAL(startRecording()),
......@@ -92,9 +94,8 @@ public slots:
}
private:
QString prefix;
QString id;
QString header;
};
#endif // DATARECORDER_H
......@@ -22,6 +22,8 @@ EyeImageProcessor::EyeImageProcessor(QString id, QObject *parent)
#endif
settings = new QSettings(gCfgDir + "/" + id + " ImageProcessor", QSettings::IniFormat);
updateConfig();
pmIdx = gPerformanceMonitor.enrol(id, "Image Processor");
}
void EyeImageProcessor::updateConfig()
......@@ -50,7 +52,7 @@ void EyeImageProcessor::process(Timestamp timestamp, const Mat &frame)
Mat prevInput = data.input;
// TODO: parametrize frame drop due to lack of processing power
if (gTimer.elapsed() - timestamp > 50)
if ( gPerformanceMonitor.shouldDrop(pmIdx, gTimer.elapsed() - timestamp, 50) )
return;
QMutexLocker locker(&cfgMutex);
......
......@@ -278,6 +278,8 @@ private:
QPointF sROI, eROI;
PupilDetectionMethod *pupilDetectionMethod;
unsigned int pmIdx;
};
#endif // EYEIMAGEPROCESSOR_H
......@@ -22,6 +22,8 @@ FieldImageProcessor::FieldImageProcessor(QString id, QObject *parent)
detectorParameters->markerBorderBits = 2;
detectorParameters->minMarkerPerimeterRate = 0.10; // TODO: determine a good value for these based on the fov and maximum detection distance
//printMarkers(); // TODO: parametrize me
pmIdx = gPerformanceMonitor.enrol(id, "Image Processor");
}
void FieldImageProcessor::updateConfig()
......@@ -42,7 +44,7 @@ void FieldImageProcessor::process(Timestamp timestamp, const Mat &frame)
Mat prevInput = data.input;
// TODO: parametrize frame drop due to lack of processing power
if (gTimer.elapsed() - timestamp > 50)
if ( gPerformanceMonitor.shouldDrop(pmIdx, gTimer.elapsed() - timestamp, 100) )
return;
QMutexLocker locker(&cfgMutex);
......
......@@ -381,6 +381,8 @@ private:
cv::Size imageSize, newImageSize;
bool forceSanitize;
void sanitizeCameraParameters(cv::Size size);
unsigned int pmIdx;
};
#endif // FIELDIMAGEPROCESSOR_H
......@@ -18,6 +18,8 @@ FrameGrabber::FrameGrabber(QString id, int code, QObject *parent) :
watchdog = new QTimer(this);
connect(watchdog, SIGNAL(timeout()), this, SIGNAL(timedout()));
watchdog->start(timeoutMs);
pmIdx = gPerformanceMonitor.enrol(id, "Frame Grabber");
}
FrameGrabber::~FrameGrabber()
......@@ -108,7 +110,8 @@ bool FrameGrabber::present(const QVideoFrame &frame)
if (success && !cvFrame.empty()) {
watchdog->start(timeoutMs);
emit newFrame(t, cvFrame);
}
} else
gPerformanceMonitor.account(pmIdx);
return success;
}
......
......@@ -45,6 +45,8 @@ private:
long unsigned int yuvBufferSize;
bool jpeg2bmp(const QVideoFrame &in, cv::Mat &cvFrame);
bool rgb32_2bmp(const QVideoFrame &in, cv::Mat &cvFrame);
unsigned int pmIdx;
};
#endif // FRAMEGRABBER_H
......@@ -108,6 +108,11 @@ MainWindow::MainWindow(QWidget *parent) :
networkStream->start(2002);
connect(gazeEstimationWidget, SIGNAL(outDataTuple(DataTuple)), networkStream, SLOT(push(DataTuple)) );
performanceMonitorWidget = new PerformanceMonitorWidget();
performanceMonitorWidget->show();
performanceMonitorWidget->move(cfg.performanceMonitorWidgetPos);
performanceMonitorWidget->resize(cfg.performanceMonitorWidgetSize);
// GUI to Widgets signals
connect(this, SIGNAL(startRecording()),
lEyeWidget, SLOT(startRecording()) );
......@@ -159,6 +164,8 @@ void MainWindow::closeEvent(QCloseEvent *event)
cfg.fieldWidgetSize = fieldWidget->size();
cfg.gazeEstimationWidgetPos = gazeEstimationWidget->pos();
cfg.gazeEstimationWidgetSize = gazeEstimationWidget->size();
cfg.performanceMonitorWidgetPos = performanceMonitorWidget->pos();
cfg.performanceMonitorWidgetSize = performanceMonitorWidget->size();
cfg.workingDirectory = QDir::currentPath();
if (settings)
cfg.save(settings);
......@@ -192,6 +199,16 @@ void MainWindow::closeEvent(QCloseEvent *event)
if (networkStream)
networkStream->deleteLater();
gPerformanceMonitor.report();
qInfo() << "Closing Performance Monitor Widget...";
if (performanceMonitorWidget) {
performanceMonitorWidget->close();
performanceMonitorWidget->deleteLater();
performanceMonitorWidget = NULL;
}
qInfo() << "Closing Log Widget...";
if (logWidget) {
gLogWidget = NULL;
......@@ -411,6 +428,11 @@ void MainWindow::on_log_clicked()
widgetButtonReact(logWidget, ui->log->isChecked());
}
void MainWindow::on_performanceMonitor_clicked()
{
widgetButtonReact(performanceMonitorWidget, ui->performanceMonitor->isChecked());
}
void MainWindow::keyPressEvent(QKeyEvent *event)
{
if (event->isAutoRepeat())
......@@ -561,3 +583,4 @@ void MainWindow::checkForOpenH264()
}
......@@ -22,6 +22,7 @@
#include "Reference.h"
#include "LogWidget.h"
#include "PerformanceMonitorWidget.h"
#include "utils.h"
......@@ -41,6 +42,8 @@ public:
fieldWidgetSize( QSize(320,240) ),
gazeEstimationWidgetPos( QPoint(0,0) ),
gazeEstimationWidgetSize( QSize(100, 100) ),
performanceMonitorWidgetPos( QPoint(0,0) ),
performanceMonitorWidgetSize( QSize(640, 240)),
workingDirectory("./"),
showOpenH264Info(true)
{}
......@@ -57,6 +60,8 @@ public:
QSize fieldWidgetSize;
QPoint gazeEstimationWidgetPos;
QSize gazeEstimationWidgetSize;
QPoint performanceMonitorWidgetPos;
QSize performanceMonitorWidgetSize;
QString workingDirectory;
bool showOpenH264Info;
......@@ -75,6 +80,8 @@ public:
settings->setValue("fieldWidgetSize", fieldWidgetSize);
settings->setValue("gazeEstimationWidgetPos", gazeEstimationWidgetPos);
settings->setValue("gazeEstimationWidgetSize", gazeEstimationWidgetSize);
settings->setValue("performanceMonitorWidgetPos", performanceMonitorWidgetPos);
settings->setValue("performanceMonitorWidgetSize", performanceMonitorWidgetSize);
settings->setValue("workingDirectory", workingDirectory);
settings->setValue("showOpenH264Info", showOpenH264Info);
}
......@@ -94,6 +101,8 @@ public:
set(settings, "fieldWidgetSize", fieldWidgetSize);
set(settings, "gazeEstimationWidgetPos", gazeEstimationWidgetPos);
set(settings, "gazeEstimationWidgetSize", gazeEstimationWidgetSize);
set(settings, "performanceMonitorWidgetPos", performanceMonitorWidgetPos);
set(settings, "performanceMonitorWidgetSize", performanceMonitorWidgetSize);
set(settings, "workingDirectory", workingDirectory);
set(settings, "showOpenH264Info", showOpenH264Info);
}
......@@ -130,6 +139,7 @@ private:
DataRecorderThread *journal;
NetworkStream * networkStream;
LogWidget *logWidget;
PerformanceMonitorWidget *performanceMonitorWidget;
QElapsedTimer elapsedTime;
int elapsedTimeUpdateTimer;
......@@ -163,6 +173,7 @@ private slots:
void showReferencesDialog();
void showAboutDialog();
void on_log_clicked();
void on_performanceMonitor_clicked();
};
#endif // MAINWINDOW_H
......@@ -6,8 +6,8 @@
<rect>
<x>0</x>
<y>0</y>
<width>319</width>
<height>371</height>
<width>252</width>
<height>444</height>
</rect>
</property>
<property name="windowTitle">
......@@ -20,6 +20,12 @@
<layout class="QGridLayout" name="gridLayout_2">
<item row="0" column="0">
<layout class="QGridLayout" name="gridLayout">
<property name="topMargin">
<number>0</number>
</property>
<property name="bottomMargin">
<number>6</number>
</property>
<property name="verticalSpacing">
<number>3</number>
</property>
......@@ -383,10 +389,16 @@
</item>
<item row="3" column="0">
<widget class="QGroupBox" name="widgetBox">
<property name="sizePolicy">
<sizepolicy hsizetype="Preferred" vsizetype="Minimum">
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
<property name="minimumSize">
<size>
<width>0</width>
<height>75</height>
<height>130</height>
</size>
</property>
<property name="title">
......@@ -443,8 +455,8 @@
</property>
</widget>
</item>
<item row="0" column="0">
<widget class="QPushButton" name="leftEyeCam">
<item row="0" column="2">
<widget class="QPushButton" name="fieldCam">
<property name="sizePolicy">
<sizepolicy hsizetype="Fixed" vsizetype="Fixed">
<horstretch>0</horstretch>
......@@ -453,7 +465,7 @@
</property>
<property name="minimumSize">
<size>
<width>0</width>
<width>40</width>
<height>40</height>
</size>
</property>
......@@ -464,7 +476,7 @@
</size>
</property>
<property name="toolTip">
<string>Toggle Left Eye Cam Widget</string>
<string>Toggle Field Cam Widget</string>
</property>
<property name="statusTip">
<string/>
......@@ -472,15 +484,12 @@
<property name="whatsThis">
<string/>
</property>
<property name="styleSheet">
<string notr="true"/>
</property>
<property name="text">
<string/>
</property>
<property name="icon">
<iconset resource="../resources.qrc">
<normaloff>:/icons/lEyeWidget.png</normaloff>:/icons/lEyeWidget.png</iconset>
<normaloff>:/icons/fieldWidget.png</normaloff>:/icons/fieldWidget.png</iconset>
</property>
<property name="iconSize">
<size>
......@@ -494,16 +503,10 @@
<property name="checked">
<bool>true</bool>
</property>
<property name="default">
<bool>false</bool>
</property>
<property name="flat">
<bool>false</bool>
</property>
</widget>
</item>
<item row="0" column="2">
<widget class="QPushButton" name="fieldCam">
<item row="0" column="0">
<widget class="QPushButton" name="leftEyeCam">
<property name="sizePolicy">
<sizepolicy hsizetype="Fixed" vsizetype="Fixed">
<horstretch>0</horstretch>
......@@ -512,7 +515,7 @@
</property>
<property name="minimumSize">
<size>
<width>40</width>
<width>0</width>
<height>40</height>
</size>
</property>
......@@ -523,7 +526,7 @@
</size>
</property>
<property name="toolTip">
<string>Toggle Field Cam Widget</string>
<string>Toggle Left Eye Cam Widget</string>
</property>
<property name="statusTip">
<string/>
......@@ -531,12 +534,15 @@
<property name="whatsThis">
<string/>
</property>
<property name="styleSheet">
<string notr="true"/>
</property>
<property name="text">
<string/>
</property>
<property name="icon">
<iconset resource="../resources.qrc">
<normaloff>:/icons/fieldWidget.png</normaloff>:/icons/fieldWidget.png</iconset>
<normaloff>:/icons/lEyeWidget.png</normaloff>:/icons/lEyeWidget.png</iconset>
</property>
<property name="iconSize">
<size>
......@@ -550,9 +556,15 @@
<property name="checked">
<bool>true</bool>
</property>
<property name="default">
<bool>false</bool>
</property>
<property name="flat">
<bool>false</bool>
</property>
</widget>
</item>
<item row="0" column="3">
<item row="0" column="4">
<widget class="QPushButton" name="gazeEstimation">
<property name="sizePolicy">
<sizepolicy hsizetype="Fixed" vsizetype="Fixed">
......@@ -602,7 +614,7 @@
</property>
</widget>
</item>
<item row="0" column="4">
<item row="2" column="0">
<widget class="QPushButton" name="log">
<property name="enabled">
<bool>true</bool>
......@@ -649,9 +661,69 @@
</property>
</widget>
</item>
<item row="2" column="1">
<widget class="QPushButton" name="performanceMonitor">
<property name="sizePolicy">
<sizepolicy hsizetype="Fixed" vsizetype="Fixed">
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
<property name="minimumSize">
<size>
<width>40</width>
<height>40</height>
</size>
</property>
<property name="maximumSize">
<size>
<width>40</width>
<height>40</height>
</size>
</property>
<property name="toolTip">
<string>Toggle Performance Monitor Widget</string>
</property>
<property name="text">
<string/>
</property>
<property name="icon">
<iconset resource="../resources.qrc">
<normaloff>:/icons/performanceMonitorWidget.png</normaloff>:/icons/performanceMonitorWidget.png</iconset>
</property>
<property name="iconSize">
<size>
<width>33</width>
<height>33</height>
</size>
</property>
<property name="checkable">
<bool>true</bool>
</property>
<property name="checked">
<bool>true</bool>
</property>
</widget>
</item>
</layout>
</widget>
</item>
<item row="4" column="0">
<spacer name="verticalSpacer">
<property name="orientation">
<enum>Qt::Vertical</enum>
</property>
<property name="sizeType">
<enum>QSizePolicy::Minimum</enum>
</property>
<property name="sizeHint" stdset="0">
<size>
<width>20</width>
<height>10</height>
</size>
</property>
</spacer>
</item>
</layout>
</item>
</layout>
......@@ -661,7 +733,7 @@
<rect>
<x>0</x>
<y>0</y>
<width>319</width>
<width>252</width>
<height>20</height>
</rect>
</property>
......
#include "PerformanceMonitor.h"
#include <QDebug>
/* NOTICE:
*
* We do not use mutexes here for performance reasons so care should be taken.
* Basic rules:
*
* 1) The performance monitor lives throughout the whole program life time,
* which guarantees valid object access.
*
* 2) Once enrolled, there is no removing it. Therefore given indexes are always
* valid (and should be unique and retrievable for a given id/stage pair!).
*
* 3) enrolled.size() == droppedFrameCount.size()
*
*/
PerformanceMonitor::PerformanceMonitor() :
frameDropEnabled(true),
delayedFrameCount(0)
{