1
0
mirror of https://github.com/qTox/qTox.git synced 2024-03-22 14:00:36 +08:00

cleanup, split

This commit is contained in:
krepa098 2014-10-08 16:37:42 +02:00
parent c5f5e4ffa9
commit de1445cdd8
6 changed files with 299 additions and 250 deletions

205
cameraworker.cpp Normal file
View File

@ -0,0 +1,205 @@
/*
Copyright (C) 2014 by Project Tox <https://tox.im>
This file is part of qTox, a Qt-based graphical interface for Tox.
This program is libre software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
See the COPYING file for more details.
*/
#include "cameraworker.h"
#include <QTimer>
#include <QDebug>
CameraWorker::CameraWorker(int index)
: clock(nullptr)
, camIndex(index)
, refCount(0)
{
}
void CameraWorker::onStart()
{
clock = new QTimer(this);
clock->setSingleShot(false);
clock->setInterval(5);
connect(clock, &QTimer::timeout, this, &CameraWorker::doWork);
emit started();
}
void CameraWorker::_suspend()
{
qDebug() << "Suspend";
clock->stop();
unsubscribe();
}
void CameraWorker::_resume()
{
qDebug() << "Resume";
subscribe();
clock->start();
}
void CameraWorker::_setProp(int prop, double val)
{
props[prop] = val;
if (cam.isOpened())
cam.set(prop, val);
}
double CameraWorker::_getProp(int prop)
{
if (!props.contains(prop))
{
subscribe();
props[prop] = cam.get(prop);
unsubscribe();
qDebug() << "ASKED " << prop << " VAL " << props[prop];
}
return props.value(prop);
}
void CameraWorker::probeResolutions()
{
if (resolutions.isEmpty())
{
subscribe();
// probe resolutions (TODO: add more)
QList<QSize> propbeRes = {
QSize( 160, 120), // QQVGA
QSize( 320, 240), // HVGA
QSize(1024, 768), // XGA
QSize( 432, 240), // WQVGA
QSize( 640, 360), // nHD
};
for (QSize res : propbeRes)
{
cam.set(CV_CAP_PROP_FRAME_WIDTH, res.width());
cam.set(CV_CAP_PROP_FRAME_HEIGHT, res.height());
double w = cam.get(CV_CAP_PROP_FRAME_WIDTH);
double h = cam.get(CV_CAP_PROP_FRAME_HEIGHT);
//qDebug() << "PROBING:" << res << " got " << w << h;
if (!resolutions.contains(QSize(w,h)))
resolutions.append(QSize(w,h));
}
unsubscribe();
}
qDebug() << resolutions;
emit resProbingFinished(resolutions);
}
void CameraWorker::applyProps()
{
if (!cam.isOpened())
return;
for(int prop : props.keys())
cam.set(prop, props.value(prop));
}
void CameraWorker::subscribe()
{
if (refCount == 0)
{
if (!cam.isOpened())
{
cam.open(camIndex);
applyProps(); // restore props
}
}
refCount++;
}
void CameraWorker::unsubscribe()
{
refCount--;
if(refCount <= 0)
{
cam.release();
}
}
void CameraWorker::doWork()
{
if (!cam.isOpened())
return;
if (queue.size() > 3)
{
queue.dequeue();
return;
}
cam >> frame;
//qDebug() << "Decoding frame";
mutex.lock();
queue.enqueue(frame);
mutex.unlock();
emit newFrameAvailable();
}
bool CameraWorker::hasFrame()
{
mutex.lock();
bool b = !queue.empty();
mutex.unlock();
return b;
}
cv::Mat3b CameraWorker::dequeueFrame()
{
mutex.lock();
cv::Mat3b f = queue.dequeue();
mutex.unlock();
return f;
}
void CameraWorker::suspend()
{
QMetaObject::invokeMethod(this, "_suspend");
}
void CameraWorker::resume()
{
QMetaObject::invokeMethod(this, "_resume");
}
void CameraWorker::setProp(int prop, double val)
{
QMetaObject::invokeMethod(this, "_setProp", Q_ARG(int, prop), Q_ARG(double, val));
}
double CameraWorker::getProp(int prop)
{
double ret = 0.0;
QMetaObject::invokeMethod(this, "_getProp", Qt::BlockingQueuedConnection, Q_RETURN_ARG(double, ret), Q_ARG(int, prop));
return ret;
}

77
cameraworker.h Normal file
View File

@ -0,0 +1,77 @@
/*
Copyright (C) 2014 by Project Tox <https://tox.im>
This file is part of qTox, a Qt-based graphical interface for Tox.
This program is libre software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
See the COPYING file for more details.
*/
#ifndef CAMERAWORKER_H
#define CAMERAWORKER_H
#include <QObject>
#include <QList>
#include <QMap>
#include <QMutex>
#include <QQueue>
#include <QSize>
#include "opencv2/opencv.hpp"
class QTimer;
class CameraWorker : public QObject
{
Q_OBJECT
public:
CameraWorker(int index);
void doWork();
bool hasFrame();
cv::Mat3b dequeueFrame();
void suspend();
void resume();
void setProp(int prop, double val);
double getProp(int prop); // blocking call!
void probeResolutions();
public slots:
void onStart();
signals:
void started();
void newFrameAvailable();
void resProbingFinished(QList<QSize> res);
private slots:
void _suspend();
void _resume();
void _setProp(int prop, double val);
double _getProp(int prop);
private:
void applyProps();
void subscribe();
void unsubscribe();
private:
QMutex mutex;
QQueue<cv::Mat3b> queue;
QTimer* clock;
cv::VideoCapture cam;
cv::Mat3b frame;
int camIndex;
QMap<int, double> props;
QList<QSize> resolutions;
int refCount;
};
#endif // CAMERAWORKER_H

View File

@ -129,7 +129,8 @@ HEADERS += widget/form/addfriendform.h \
widget/tool/chatactions/systemmessageaction.h \ widget/tool/chatactions/systemmessageaction.h \
widget/tool/chatactions/actionaction.h \ widget/tool/chatactions/actionaction.h \
widget/maskablepixmapwidget.h \ widget/maskablepixmapwidget.h \
videosource.h videosource.h \
cameraworker.h
SOURCES += \ SOURCES += \
widget/form/addfriendform.cpp \ widget/form/addfriendform.cpp \
@ -175,4 +176,5 @@ SOURCES += \
widget/tool/chatactions/filetransferaction.cpp \ widget/tool/chatactions/filetransferaction.cpp \
widget/tool/chatactions/systemmessageaction.cpp \ widget/tool/chatactions/systemmessageaction.cpp \
widget/tool/chatactions/actionaction.cpp \ widget/tool/chatactions/actionaction.cpp \
widget/maskablepixmapwidget.cpp widget/maskablepixmapwidget.cpp \
cameraworker.cpp

View File

@ -16,10 +16,9 @@
#include "camera.h" #include "camera.h"
#include "widget.h" #include "widget.h"
#include <QtConcurrent/QtConcurrentRun> #include "cameraworker.h"
#include <QDebug> #include <QDebug>
#include <QThread> #include <QThread>
#include <QTimer>
Camera* Camera::instance = nullptr; Camera* Camera::instance = nullptr;
@ -28,18 +27,17 @@ Camera::Camera()
, workerThread(nullptr) , workerThread(nullptr)
, worker(nullptr) , worker(nullptr)
{ {
qDebug() << "New Worker"; worker = new CameraWorker(0);
worker = new SelfCamWorker(0);
workerThread = new QThread(); workerThread = new QThread();
worker->moveToThread(workerThread); worker->moveToThread(workerThread);
connect(workerThread, &QThread::started, worker, &SelfCamWorker::onStart); connect(workerThread, &QThread::started, worker, &CameraWorker::onStart);
connect(workerThread, &QThread::finished, worker, &SelfCamWorker::deleteLater); connect(workerThread, &QThread::finished, worker, &CameraWorker::deleteLater);
connect(workerThread, &QThread::deleteLater, worker, &SelfCamWorker::deleteLater); connect(workerThread, &QThread::deleteLater, worker, &CameraWorker::deleteLater);
connect(worker, &SelfCamWorker::started, this, &Camera::onWorkerStarted); connect(worker, &CameraWorker::started, this, &Camera::onWorkerStarted);
connect(worker, &SelfCamWorker::newFrameAvailable, this, &Camera::onNewFrameAvailable); connect(worker, &CameraWorker::newFrameAvailable, this, &Camera::onNewFrameAvailable);
connect(worker, &SelfCamWorker::resProbingFinished, this, &Camera::onResProbingFinished); connect(worker, &CameraWorker::resProbingFinished, this, &Camera::onResProbingFinished);
workerThread->start(); workerThread->start();
} }
@ -222,7 +220,7 @@ void Camera::lock()
mutex.lock(); mutex.lock();
if (worker->hasFrame()) if (worker->hasFrame())
currFrame = worker->deqeueFrame(); currFrame = worker->dequeueFrame();
} }
void Camera::unlock() void Camera::unlock()
@ -242,192 +240,3 @@ Camera* Camera::getInstance()
return instance; return instance;
} }
// ====================
// WORKER
// ====================
SelfCamWorker::SelfCamWorker(int index)
: clock(nullptr)
, camIndex(index)
, refCount(0)
{
}
void SelfCamWorker::onStart()
{
clock = new QTimer(this);
clock->setSingleShot(false);
clock->setInterval(5);
connect(clock, &QTimer::timeout, this, &SelfCamWorker::doWork);
emit started();
}
void SelfCamWorker::_suspend()
{
qDebug() << "Suspend";
clock->stop();
unsubscribe();
}
void SelfCamWorker::_resume()
{
qDebug() << "Resume";
subscribe();
clock->start();
}
void SelfCamWorker::_setProp(int prop, double val)
{
props[prop] = val;
if (cam.isOpened())
cam.set(prop, val);
}
double SelfCamWorker::_getProp(int prop)
{
if (!props.contains(prop))
{
subscribe();
props[prop] = cam.get(prop);
unsubscribe();
qDebug() << "ASKED " << prop << " VAL " << props[prop];
}
return props.value(prop);
}
void SelfCamWorker::probeResolutions()
{
if (resolutions.isEmpty())
{
subscribe();
// probe resolutions (TODO: add more)
QList<QSize> propbeRes = {
QSize( 160, 120), // QQVGA
QSize( 320, 240), // HVGA
QSize(1024, 768), // XGA
QSize( 432, 240), // WQVGA
QSize( 640, 360), // nHD
};
for (QSize res : propbeRes)
{
cam.set(CV_CAP_PROP_FRAME_WIDTH, res.width());
cam.set(CV_CAP_PROP_FRAME_HEIGHT, res.height());
double w = cam.get(CV_CAP_PROP_FRAME_WIDTH);
double h = cam.get(CV_CAP_PROP_FRAME_HEIGHT);
//qDebug() << "PROBING:" << res << " got " << w << h;
if (!resolutions.contains(QSize(w,h)))
resolutions.append(QSize(w,h));
}
unsubscribe();
}
qDebug() << resolutions;
emit resProbingFinished(resolutions);
}
void SelfCamWorker::applyProps()
{
if (!cam.isOpened())
return;
for(int prop : props.keys())
cam.set(prop, props.value(prop));
}
void SelfCamWorker::subscribe()
{
if (refCount == 0)
{
if (!cam.isOpened())
{
cam.open(camIndex);
applyProps(); // restore props
}
}
refCount++;
}
void SelfCamWorker::unsubscribe()
{
refCount--;
if(refCount <= 0)
{
cam.release();
}
}
void SelfCamWorker::doWork()
{
if (!cam.isOpened())
return;
if (qeue.size() > 3)
{
qeue.dequeue();
return;
}
cam >> frame;
//qDebug() << "Decoding frame";
mutex.lock();
qeue.enqueue(frame);
mutex.unlock();
emit newFrameAvailable();
}
bool SelfCamWorker::hasFrame()
{
mutex.lock();
bool b = !qeue.empty();
mutex.unlock();
return b;
}
cv::Mat3b SelfCamWorker::deqeueFrame()
{
mutex.lock();
cv::Mat3b f = qeue.dequeue();
mutex.unlock();
return f;
}
void SelfCamWorker::suspend()
{
QMetaObject::invokeMethod(this, "_suspend");
}
void SelfCamWorker::resume()
{
QMetaObject::invokeMethod(this, "_resume");
}
void SelfCamWorker::setProp(int prop, double val)
{
QMetaObject::invokeMethod(this, "_setProp", Q_ARG(int, prop), Q_ARG(double, val));
}
double SelfCamWorker::getProp(int prop)
{
double ret = 0.0;
QMetaObject::invokeMethod(this, "_getProp", Qt::BlockingQueuedConnection, Q_RETURN_ARG(double, ret), Q_ARG(int, prop));
return ret;
}

View File

@ -26,58 +26,14 @@
#include "opencv2/opencv.hpp" #include "opencv2/opencv.hpp"
#include "videosource.h" #include "videosource.h"
class CameraWorker;
/** /**
* This class is a wrapper to share a camera's captured video frames * This class is a wrapper to share a camera's captured video frames
* It allows objects to suscribe and unsuscribe to the stream, starting * It allows objects to suscribe and unsuscribe to the stream, starting
* the camera only when needed, and giving access to the last frames * the camera only when needed, and giving access to the last frames
**/ **/
class SelfCamWorker : public QObject
{
Q_OBJECT
public:
SelfCamWorker(int index);
void doWork();
bool hasFrame();
cv::Mat3b deqeueFrame();
void suspend();
void resume();
void setProp(int prop, double val);
double getProp(int prop); // blocking call!
void probeResolutions();
public slots:
void onStart();
signals:
void started();
void newFrameAvailable();
void resProbingFinished(QList<QSize> res);
private slots:
void _suspend();
void _resume();
void _setProp(int prop, double val);
double _getProp(int prop);
private:
void applyProps();
void subscribe();
void unsubscribe();
private:
QMutex mutex;
QQueue<cv::Mat3b> qeue;
QTimer* clock;
cv::VideoCapture cam;
cv::Mat3b frame;
int camIndex;
QMap<int, double> props;
QList<QSize> resolutions;
int refCount;
};
class Camera : public VideoSource class Camera : public VideoSource
{ {
Q_OBJECT Q_OBJECT
@ -123,7 +79,7 @@ private:
QMutex mutex; QMutex mutex;
QThread* workerThread; QThread* workerThread;
SelfCamWorker* worker; CameraWorker* worker;
QList<QSize> resolutions; QList<QSize> resolutions;

View File

@ -17,7 +17,7 @@
<item> <item>
<widget class="QGroupBox" name="groupBox"> <widget class="QGroupBox" name="groupBox">
<property name="title"> <property name="title">
<string>Volume Settings</string> <string>Volume Settings (Stubs)</string>
</property> </property>
<layout class="QFormLayout" name="formLayout_2"> <layout class="QFormLayout" name="formLayout_2">
<item row="0" column="0"> <item row="0" column="0">