Merge pull request #4698 from ctrlaltdavid/fps-facetracker

Facetracker FPS refactor
This commit is contained in:
Clément Brisset 2015-04-28 14:04:17 +02:00
commit bc8f6708b6
6 changed files with 98 additions and 82 deletions

View file

@ -136,9 +136,6 @@ struct Packet {
const float STARTING_DDE_MESSAGE_TIME = 0.033f; const float STARTING_DDE_MESSAGE_TIME = 0.033f;
const int FPS_TIMER_DELAY = 2000; // ms
const int FPS_TIMER_DURATION = 2000; // ms
DdeFaceTracker::DdeFaceTracker() : DdeFaceTracker::DdeFaceTracker() :
DdeFaceTracker(QHostAddress::Any, DDE_SERVER_PORT, DDE_CONTROL_PORT) DdeFaceTracker(QHostAddress::Any, DDE_SERVER_PORT, DDE_CONTROL_PORT)
{ {
@ -147,6 +144,7 @@ DdeFaceTracker::DdeFaceTracker() :
DdeFaceTracker::DdeFaceTracker(const QHostAddress& host, quint16 serverPort, quint16 controlPort) : DdeFaceTracker::DdeFaceTracker(const QHostAddress& host, quint16 serverPort, quint16 controlPort) :
_ddeProcess(NULL), _ddeProcess(NULL),
_ddeStopping(false),
_host(host), _host(host),
_serverPort(serverPort), _serverPort(serverPort),
_controlPort(controlPort), _controlPort(controlPort),
@ -171,9 +169,7 @@ DdeFaceTracker::DdeFaceTracker(const QHostAddress& host, quint16 serverPort, qui
_lastLeftEyeBlink(0.0f), _lastLeftEyeBlink(0.0f),
_filteredLeftEyeBlink(0.0f), _filteredLeftEyeBlink(0.0f),
_lastRightEyeBlink(0.0f), _lastRightEyeBlink(0.0f),
_filteredRightEyeBlink(0.0f), _filteredRightEyeBlink(0.0f)
_isCalculatingFPS(false),
_frameCount(0)
{ {
_coefficients.resize(NUM_FACESHIFT_BLENDSHAPES); _coefficients.resize(NUM_FACESHIFT_BLENDSHAPES);
@ -201,46 +197,50 @@ void DdeFaceTracker::setEnabled(bool enabled) {
if (enabled && !_ddeProcess) { if (enabled && !_ddeProcess) {
// Terminate any existing DDE process, perhaps left running after an Interface crash // Terminate any existing DDE process, perhaps left running after an Interface crash
_udpSocket.writeDatagram(DDE_EXIT_COMMAND, DDE_SERVER_ADDR, _controlPort); _udpSocket.writeDatagram(DDE_EXIT_COMMAND, DDE_SERVER_ADDR, _controlPort);
_ddeStopping = false;
qDebug() << "[Info] DDE Face Tracker Starting"; qCDebug(interfaceapp) << "DDE Face Tracker: Starting";
_ddeProcess = new QProcess(qApp); _ddeProcess = new QProcess(qApp);
connect(_ddeProcess, SIGNAL(finished(int, QProcess::ExitStatus)), SLOT(processFinished(int, QProcess::ExitStatus))); connect(_ddeProcess, SIGNAL(finished(int, QProcess::ExitStatus)), SLOT(processFinished(int, QProcess::ExitStatus)));
_ddeProcess->start(QCoreApplication::applicationDirPath() + DDE_PROGRAM_PATH, DDE_ARGUMENTS); _ddeProcess->start(QCoreApplication::applicationDirPath() + DDE_PROGRAM_PATH, DDE_ARGUMENTS);
} }
if (!enabled && _ddeProcess) { if (!enabled && _ddeProcess) {
_ddeStopping = true;
_udpSocket.writeDatagram(DDE_EXIT_COMMAND, DDE_SERVER_ADDR, _controlPort); _udpSocket.writeDatagram(DDE_EXIT_COMMAND, DDE_SERVER_ADDR, _controlPort);
delete _ddeProcess; qCDebug(interfaceapp) << "DDE Face Tracker: Stopping";
_ddeProcess = NULL;
qDebug() << "[Info] DDE Face Tracker Stopped";
} }
#endif #endif
} }
void DdeFaceTracker::processFinished(int exitCode, QProcess::ExitStatus exitStatus) { void DdeFaceTracker::processFinished(int exitCode, QProcess::ExitStatus exitStatus) {
if (_ddeProcess) { if (_ddeProcess) {
// DDE crashed or was manually terminated if (_ddeStopping) {
qDebug() << "[Info] DDE Face Tracker Stopped Unexpectedly"; qCDebug(interfaceapp) << "DDE Face Tracker: Stopped";
} else {
qCWarning(interfaceapp) << "DDE Face Tracker: Stopped unexpectedly";
Menu::getInstance()->setIsOptionChecked(MenuOption::NoFaceTracking, true);
}
_udpSocket.close(); _udpSocket.close();
delete _ddeProcess;
_ddeProcess = NULL; _ddeProcess = NULL;
Menu::getInstance()->setIsOptionChecked(MenuOption::NoFaceTracking, true);
} }
} }
void DdeFaceTracker::reset() { void DdeFaceTracker::reset() {
_reset = true; if (_udpSocket.state() == QAbstractSocket::BoundState) {
_reset = true;
qDebug() << "[Info] Reset DDE Tracking"; qCDebug(interfaceapp) << "DDE Face Tracker: Reset";
const char* DDE_RESET_COMMAND = "reset";
_udpSocket.writeDatagram(DDE_RESET_COMMAND, DDE_SERVER_ADDR, _controlPort);
// Log camera FPS after a reset const char* DDE_RESET_COMMAND = "reset";
if (!_isCalculatingFPS) { _udpSocket.writeDatagram(DDE_RESET_COMMAND, DDE_SERVER_ADDR, _controlPort);
QTimer::singleShot(FPS_TIMER_DELAY, this, SLOT(startFPSTimer()));
_isCalculatingFPS = true; FaceTracker::reset();
_reset = true;
} }
_reset = true;
} }
bool DdeFaceTracker::isActive() const { bool DdeFaceTracker::isActive() const {
@ -250,7 +250,7 @@ bool DdeFaceTracker::isActive() const {
//private slots and methods //private slots and methods
void DdeFaceTracker::socketErrorOccurred(QAbstractSocket::SocketError socketError) { void DdeFaceTracker::socketErrorOccurred(QAbstractSocket::SocketError socketError) {
qCDebug(interfaceapp) << "[Error] DDE Face Tracker Socket Error: " << _udpSocket.errorString(); qCWarning(interfaceapp) << "DDE Face Tracker: Socket error: " << _udpSocket.errorString();
} }
void DdeFaceTracker::socketStateChanged(QAbstractSocket::SocketState socketState) { void DdeFaceTracker::socketStateChanged(QAbstractSocket::SocketState socketState) {
@ -278,7 +278,7 @@ void DdeFaceTracker::socketStateChanged(QAbstractSocket::SocketState socketState
state = "Unconnected"; state = "Unconnected";
break; break;
} }
qCDebug(interfaceapp) << "[Info] DDE Face Tracker Socket: " << state; qCDebug(interfaceapp) << "DDE Face Tracker: Socket: " << state;
} }
void DdeFaceTracker::readPendingDatagrams() { void DdeFaceTracker::readPendingDatagrams() {
@ -419,23 +419,10 @@ void DdeFaceTracker::decodePacket(const QByteArray& buffer) {
} }
_lastMessageReceived = usecsNow; _lastMessageReceived = usecsNow;
// Count frames if timing FaceTracker::countFrame();
if (_isCalculatingFPS) {
_frameCount++;
}
} else { } else {
qCDebug(interfaceapp) << "[Error] DDE Face Tracker Decode Error"; qCWarning(interfaceapp) << "DDE Face Tracker: Decode error";
} }
_lastReceiveTimestamp = usecTimestampNow(); _lastReceiveTimestamp = usecTimestampNow();
} }
void DdeFaceTracker::startFPSTimer() {
_frameCount = 0;
QTimer::singleShot(FPS_TIMER_DURATION, this, SLOT(finishFPSTimer()));
}
void DdeFaceTracker::finishFPSTimer() {
qDebug() << "[Info] DDE FPS =" << (float)_frameCount / ((float)FPS_TIMER_DURATION / 1000.0f);
_isCalculatingFPS = false;
}

View file

@ -59,15 +59,13 @@ private slots:
void readPendingDatagrams(); void readPendingDatagrams();
void socketStateChanged(QAbstractSocket::SocketState socketState); void socketStateChanged(QAbstractSocket::SocketState socketState);
void startFPSTimer();
void finishFPSTimer();
private: private:
DdeFaceTracker(); DdeFaceTracker();
DdeFaceTracker(const QHostAddress& host, quint16 serverPort, quint16 controlPort); DdeFaceTracker(const QHostAddress& host, quint16 serverPort, quint16 controlPort);
~DdeFaceTracker(); virtual ~DdeFaceTracker();
QProcess* _ddeProcess; QProcess* _ddeProcess;
bool _ddeStopping;
QHostAddress _host; QHostAddress _host;
quint16 _serverPort; quint16 _serverPort;
@ -111,9 +109,6 @@ private:
float _filteredLeftEyeBlink; float _filteredLeftEyeBlink;
float _lastRightEyeBlink; float _lastRightEyeBlink;
float _filteredRightEyeBlink; float _filteredRightEyeBlink;
bool _isCalculatingFPS;
int _frameCount;
}; };
#endif // hifi_DdeFaceTracker_h #endif // hifi_DdeFaceTracker_h

View file

@ -9,9 +9,21 @@
// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html // See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html
// //
#include <QTimer>
#include <GLMHelpers.h> #include <GLMHelpers.h>
#include "FaceTracker.h" #include "FaceTracker.h"
#include "InterfaceLogging.h"
const int FPS_TIMER_DELAY = 2000; // ms
const int FPS_TIMER_DURATION = 2000; // ms
FaceTracker::FaceTracker() :
_isCalculatingFPS(false),
_frameCount(0)
{
}
inline float FaceTracker::getBlendshapeCoefficient(int index) const { inline float FaceTracker::getBlendshapeCoefficient(int index) const {
return isValidBlendshapeIndex(index) ? glm::mix(0.0f, _blendshapeCoefficients[index], getFadeCoefficient()) return isValidBlendshapeIndex(index) ? glm::mix(0.0f, _blendshapeCoefficients[index], getFadeCoefficient())
@ -65,4 +77,27 @@ void FaceTracker::update(float deltaTime) {
_relaxationStatus = glm::clamp(_relaxationStatus - deltaTime / RELAXATION_TIME, 0.0f, 1.0f); _relaxationStatus = glm::clamp(_relaxationStatus - deltaTime / RELAXATION_TIME, 0.0f, 1.0f);
_fadeCoefficient = std::exp(-(1.0f - _relaxationStatus) * INVERSE_AT_EPSILON); _fadeCoefficient = std::exp(-(1.0f - _relaxationStatus) * INVERSE_AT_EPSILON);
} }
} }
void FaceTracker::reset() {
if (isActive() && !_isCalculatingFPS) {
QTimer::singleShot(FPS_TIMER_DELAY, this, SLOT(startFPSTimer()));
_isCalculatingFPS = true;
}
}
void FaceTracker::startFPSTimer() {
_frameCount = 0;
QTimer::singleShot(FPS_TIMER_DURATION, this, SLOT(finishFPSTimer()));
}
void FaceTracker::countFrame() {
if (_isCalculatingFPS) {
_frameCount++;
}
}
void FaceTracker::finishFPSTimer() {
qCDebug(interfaceapp) << "Face tracker FPS =" << (float)_frameCount / ((float)FPS_TIMER_DURATION / 1000.0f);
_isCalculatingFPS = false;
}

View file

@ -28,7 +28,7 @@ public:
virtual void init() {} virtual void init() {}
virtual void update(float deltaTime); virtual void update(float deltaTime);
virtual void reset() {} virtual void reset();
float getFadeCoefficient() const; float getFadeCoefficient() const;
@ -44,6 +44,9 @@ public:
float getBlendshapeCoefficient(int index) const; float getBlendshapeCoefficient(int index) const;
protected: protected:
FaceTracker();
virtual ~FaceTracker() {};
glm::vec3 _headTranslation = glm::vec3(0.0f); glm::vec3 _headTranslation = glm::vec3(0.0f);
glm::quat _headRotation = glm::quat(); glm::quat _headRotation = glm::quat();
float _estimatedEyePitch = 0.0f; float _estimatedEyePitch = 0.0f;
@ -52,6 +55,16 @@ protected:
float _relaxationStatus = 0.0f; // Between 0.0f and 1.0f float _relaxationStatus = 0.0f; // Between 0.0f and 1.0f
float _fadeCoefficient = 0.0f; // Between 0.0f and 1.0f float _fadeCoefficient = 0.0f; // Between 0.0f and 1.0f
void countFrame();
private slots:
void startFPSTimer();
void finishFPSTimer();
private:
bool _isCalculatingFPS;
int _frameCount;
}; };
#endif // hifi_FaceTracker_h #endif // hifi_FaceTracker_h

View file

@ -30,20 +30,16 @@ const QString DEFAULT_FACESHIFT_HOSTNAME = "localhost";
const quint16 FACESHIFT_PORT = 33433; const quint16 FACESHIFT_PORT = 33433;
const float DEFAULT_FACESHIFT_EYE_DEFLECTION = 0.25f; const float DEFAULT_FACESHIFT_EYE_DEFLECTION = 0.25f;
const int FPS_TIMER_DELAY = 2000; // ms
const int FPS_TIMER_DURATION = 2000; // ms
Faceshift::Faceshift() : Faceshift::Faceshift() :
_eyeDeflection("faceshiftEyeDeflection", DEFAULT_FACESHIFT_EYE_DEFLECTION), _eyeDeflection("faceshiftEyeDeflection", DEFAULT_FACESHIFT_EYE_DEFLECTION),
_hostname("faceshiftHostname", DEFAULT_FACESHIFT_HOSTNAME), _hostname("faceshiftHostname", DEFAULT_FACESHIFT_HOSTNAME)
_isCalculatingFPS(false),
_frameCount(0)
{ {
#ifdef HAVE_FACESHIFT #ifdef HAVE_FACESHIFT
connect(&_tcpSocket, SIGNAL(connected()), SLOT(noteConnected())); connect(&_tcpSocket, SIGNAL(connected()), SLOT(noteConnected()));
connect(&_tcpSocket, SIGNAL(error(QAbstractSocket::SocketError)), SLOT(noteError(QAbstractSocket::SocketError))); connect(&_tcpSocket, SIGNAL(error(QAbstractSocket::SocketError)), SLOT(noteError(QAbstractSocket::SocketError)));
connect(&_tcpSocket, SIGNAL(readyRead()), SLOT(readFromSocket())); connect(&_tcpSocket, SIGNAL(readyRead()), SLOT(readFromSocket()));
connect(&_tcpSocket, SIGNAL(stateChanged(QAbstractSocket::SocketState)), SIGNAL(connectionStateChanged())); connect(&_tcpSocket, SIGNAL(stateChanged(QAbstractSocket::SocketState)), SIGNAL(connectionStateChanged()));
connect(&_tcpSocket, SIGNAL(disconnected()), SLOT(noteDisconnected()));
connect(&_udpSocket, SIGNAL(readyRead()), SLOT(readPendingDatagrams())); connect(&_udpSocket, SIGNAL(readyRead()), SLOT(readPendingDatagrams()));
@ -83,15 +79,13 @@ void Faceshift::update(float deltaTime) {
void Faceshift::reset() { void Faceshift::reset() {
if (_tcpSocket.state() == QAbstractSocket::ConnectedState) { if (_tcpSocket.state() == QAbstractSocket::ConnectedState) {
qCDebug(interfaceapp, "Faceshift: Reset");
FaceTracker::reset();
string message; string message;
fsBinaryStream::encode_message(message, fsMsgCalibrateNeutral()); fsBinaryStream::encode_message(message, fsMsgCalibrateNeutral());
send(message); send(message);
// Log camera FPS after a reset
if (!_isCalculatingFPS) {
QTimer::singleShot(FPS_TIMER_DELAY, this, SLOT(startFPSTimer()));
_isCalculatingFPS = true;
}
} }
_longTermAverageInitialized = false; _longTermAverageInitialized = false;
} }
@ -138,6 +132,7 @@ void Faceshift::setTCPEnabled(bool enabled) {
if ((_tcpEnabled = enabled)) { if ((_tcpEnabled = enabled)) {
connectSocket(); connectSocket();
} else { } else {
qCDebug(interfaceapp, "Faceshift: Disconnecting...");
_tcpSocket.disconnectFromHost(); _tcpSocket.disconnectFromHost();
} }
#endif #endif
@ -156,7 +151,7 @@ void Faceshift::connectSocket() {
void Faceshift::noteConnected() { void Faceshift::noteConnected() {
#ifdef HAVE_FACESHIFT #ifdef HAVE_FACESHIFT
qCDebug(interfaceapp, "Faceshift: Connected."); qCDebug(interfaceapp, "Faceshift: Connected");
// request the list of blendshape names // request the list of blendshape names
string message; string message;
fsBinaryStream::encode_message(message, fsMsgSendBlendshapeNames()); fsBinaryStream::encode_message(message, fsMsgSendBlendshapeNames());
@ -164,10 +159,16 @@ void Faceshift::noteConnected() {
#endif #endif
} }
void Faceshift::noteDisconnected() {
#ifdef HAVE_FACESHIFT
qCDebug(interfaceapp, "Faceshift: Disconnected");
#endif
}
void Faceshift::noteError(QAbstractSocket::SocketError error) { void Faceshift::noteError(QAbstractSocket::SocketError error) {
if (!_tcpRetryCount) { if (!_tcpRetryCount) {
// Only spam log with fail to connect the first time, so that we can keep waiting for server // Only spam log with fail to connect the first time, so that we can keep waiting for server
qCDebug(interfaceapp) << "Faceshift: " << _tcpSocket.errorString(); qCWarning(interfaceapp) << "Faceshift: " << _tcpSocket.errorString();
} }
// retry connection after a 2 second delay // retry connection after a 2 second delay
if (_tcpEnabled) { if (_tcpEnabled) {
@ -294,10 +295,8 @@ void Faceshift::receive(const QByteArray& buffer) {
} }
} }
#endif #endif
// Count frames if timing
if (_isCalculatingFPS) { FaceTracker::countFrame();
_frameCount++;
}
} }
void Faceshift::setEyeDeflection(float faceshiftEyeDeflection) { void Faceshift::setEyeDeflection(float faceshiftEyeDeflection) {
@ -308,12 +307,3 @@ void Faceshift::setHostname(const QString& hostname) {
_hostname.set(hostname); _hostname.set(hostname);
} }
void Faceshift::startFPSTimer() {
_frameCount = 0;
QTimer::singleShot(FPS_TIMER_DURATION, this, SLOT(finishFPSTimer()));
}
void Faceshift::finishFPSTimer() {
qCDebug(interfaceapp) << "Faceshift: FPS =" << (float)_frameCount / ((float)FPS_TIMER_DURATION / 1000.0f);
_isCalculatingFPS = false;
}

View file

@ -95,8 +95,7 @@ private slots:
void noteError(QAbstractSocket::SocketError error); void noteError(QAbstractSocket::SocketError error);
void readPendingDatagrams(); void readPendingDatagrams();
void readFromSocket(); void readFromSocket();
void startFPSTimer(); void noteDisconnected();
void finishFPSTimer();
private: private:
Faceshift(); Faceshift();
@ -154,9 +153,6 @@ private:
int _mouthSmileRightIndex = 29; int _mouthSmileRightIndex = 29;
int _jawOpenIndex = 21; int _jawOpenIndex = 21;
bool _isCalculatingFPS;
int _frameCount;
}; };
#endif // hifi_Faceshift_h #endif // hifi_Faceshift_h