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

set/get props, cleanup

This commit is contained in:
krepa098 2014-10-08 15:48:02 +02:00
parent 3e234bd076
commit 200b7bc395
4 changed files with 188 additions and 113 deletions

View File

@ -37,10 +37,17 @@ Camera::Camera()
connect(workerThread, &QThread::started, worker, &SelfCamWorker::onStart); connect(workerThread, &QThread::started, worker, &SelfCamWorker::onStart);
connect(workerThread, &QThread::finished, worker, &SelfCamWorker::deleteLater); connect(workerThread, &QThread::finished, worker, &SelfCamWorker::deleteLater);
connect(workerThread, &QThread::deleteLater, worker, &SelfCamWorker::deleteLater); connect(workerThread, &QThread::deleteLater, worker, &SelfCamWorker::deleteLater);
connect(worker, &SelfCamWorker::started, this, &Camera::onWorkerStarted);
connect(worker, &SelfCamWorker::newFrameAvailable, this, &Camera::onNewFrameAvailable); connect(worker, &SelfCamWorker::newFrameAvailable, this, &Camera::onNewFrameAvailable);
connect(worker, &SelfCamWorker::resProbingFinished, this, &Camera::onResProbingFinished);
workerThread->start(); workerThread->start();
} }
void Camera::onWorkerStarted()
{
worker->probeResolutions();
}
Camera::~Camera() Camera::~Camera()
{ {
workerThread->exit(); workerThread->exit();
@ -50,16 +57,9 @@ Camera::~Camera()
void Camera::subscribe() void Camera::subscribe()
{ {
if (refcount <= 0) if (refcount <= 0)
{
refcount = 1;
//mode.res.setWidth(cam.get(CV_CAP_PROP_FRAME_WIDTH));
//mode.res.setHeight(cam.get(CV_CAP_PROP_FRAME_HEIGHT));
worker->resume(); worker->resume();
}
else refcount++;
refcount++;
} }
void Camera::unsubscribe() void Camera::unsubscribe()
@ -75,10 +75,7 @@ void Camera::unsubscribe()
cv::Mat Camera::getLastFrame() cv::Mat Camera::getLastFrame()
{ {
cv::Mat frame; return currFrame;
cam >> frame;
return frame;
} }
vpx_image Camera::getLastVPXImage() vpx_image Camera::getLastVPXImage()
@ -129,77 +126,39 @@ vpx_image Camera::getLastVPXImage()
return img; return img;
} }
QList<Camera::VideoMode> Camera::getVideoModes() QList<QSize> Camera::getSupportedResolutions()
{ {
// probe resolutions return resolutions;
QList<QSize> resolutions = {
QSize( 160, 120), // QQVGA
QSize( 320, 240), // HVGA
QSize(1024, 768), // XGA
QSize( 432, 240), // WQVGA
QSize( 640, 360), // nHD
};
QList<VideoMode> modes;
for (QSize res : resolutions)
{
mutex.lock();
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 (w == res.width() && h == res.height())
{
modes.append({res, 60}); // assume 60fps for now
}
mutex.unlock();
}
return modes;
} }
Camera::VideoMode Camera::getBestVideoMode() QSize Camera::getBestVideoMode()
{ {
int bestScore = 0; int bestScore = 0;
VideoMode bestMode; QSize bestRes;
for (VideoMode mode : getVideoModes()) for (QSize res : getSupportedResolutions())
{ {
int score = mode.res.width() * mode.res.height(); int score = res.width() * res.height();
if (score > bestScore) if (score > bestScore)
{ {
bestScore = score; bestScore = score;
bestMode = mode; bestRes = res;
} }
} }
return bestMode; return bestRes;
} }
void Camera::setVideoMode(Camera::VideoMode mode) void Camera::setResolution(QSize res)
{ {
if (cam.isOpened()) worker->setProp(CV_CAP_PROP_FRAME_WIDTH, res.width());
{ worker->setProp(CV_CAP_PROP_FRAME_HEIGHT, res.height());
mutex.lock();
cam.set(CV_CAP_PROP_FRAME_WIDTH, mode.res.width());
cam.set(CV_CAP_PROP_FRAME_HEIGHT, mode.res.height());
mode.res.setWidth(cam.get(CV_CAP_PROP_FRAME_WIDTH));
mode.res.setHeight(cam.get(CV_CAP_PROP_FRAME_HEIGHT));
mutex.unlock();
qDebug() << "VIDEO MODE" << mode.res;
}
} }
Camera::VideoMode Camera::getVideoMode() QSize Camera::getResolution()
{ {
return VideoMode{QSize(cam.get(CV_CAP_PROP_FRAME_WIDTH), cam.get(CV_CAP_PROP_FRAME_HEIGHT)), 60}; return QSize(worker->getProp(CV_CAP_PROP_FRAME_WIDTH), worker->getProp(CV_CAP_PROP_FRAME_HEIGHT));
} }
void Camera::setProp(Camera::Prop prop, double val) void Camera::setProp(Camera::Prop prop, double val)
@ -207,16 +166,16 @@ void Camera::setProp(Camera::Prop prop, double val)
switch (prop) switch (prop)
{ {
case BRIGHTNESS: case BRIGHTNESS:
cam.set(CV_CAP_PROP_BRIGHTNESS, val); worker->setProp(CV_CAP_PROP_BRIGHTNESS, val);
break; break;
case SATURATION: case SATURATION:
cam.set(CV_CAP_PROP_SATURATION, val); worker->setProp(CV_CAP_PROP_SATURATION, val);
break; break;
case CONTRAST: case CONTRAST:
cam.set(CV_CAP_PROP_CONTRAST, val); worker->setProp(CV_CAP_PROP_CONTRAST, val);
break; break;
case HUE: case HUE:
cam.set(CV_CAP_PROP_HUE, val); worker->setProp(CV_CAP_PROP_HUE, val);
break; break;
} }
} }
@ -226,13 +185,13 @@ double Camera::getProp(Camera::Prop prop)
switch (prop) switch (prop)
{ {
case BRIGHTNESS: case BRIGHTNESS:
return cam.get(CV_CAP_PROP_BRIGHTNESS); return worker->getProp(CV_CAP_PROP_BRIGHTNESS);
case SATURATION: case SATURATION:
return cam.get(CV_CAP_PROP_SATURATION); return worker->getProp(CV_CAP_PROP_SATURATION);
case CONTRAST: case CONTRAST:
return cam.get(CV_CAP_PROP_CONTRAST); return worker->getProp(CV_CAP_PROP_CONTRAST);
case HUE: case HUE:
return cam.get(CV_CAP_PROP_HUE); return worker->getProp(CV_CAP_PROP_HUE);
} }
return 0.0; return 0.0;
@ -243,6 +202,11 @@ void Camera::onNewFrameAvailable()
emit frameAvailable(); emit frameAvailable();
} }
void Camera::onResProbingFinished(QList<QSize> res)
{
resolutions = res;
}
void *Camera::getData() void *Camera::getData()
{ {
return currFrame.data; return currFrame.data;
@ -257,9 +221,6 @@ void Camera::lock()
{ {
mutex.lock(); mutex.lock();
mode.res.setWidth(currFrame.cols);
mode.res.setHeight(currFrame.rows);
if (worker->hasFrame()) if (worker->hasFrame())
currFrame = worker->deqeueFrame(); currFrame = worker->deqeueFrame();
} }
@ -289,6 +250,7 @@ Camera* Camera::getInstance()
SelfCamWorker::SelfCamWorker(int index) SelfCamWorker::SelfCamWorker(int index)
: clock(nullptr) : clock(nullptr)
, camIndex(index) , camIndex(index)
, refCount(0)
{ {
} }
@ -296,26 +258,115 @@ void SelfCamWorker::onStart()
{ {
clock = new QTimer(this); clock = new QTimer(this);
clock->setSingleShot(false); clock->setSingleShot(false);
clock->setInterval(1); clock->setInterval(5);
connect(clock, &QTimer::timeout, this, &SelfCamWorker::doWork); connect(clock, &QTimer::timeout, this, &SelfCamWorker::doWork);
clock->start();
cam.open(camIndex); emit started();
} }
void SelfCamWorker::_suspend() void SelfCamWorker::_suspend()
{ {
qDebug() << "Suspend"; qDebug() << "Suspend";
if (cam.isOpened()) clock->stop();
cam.release(); unsubscribe();
} }
void SelfCamWorker::_resume() void SelfCamWorker::_resume()
{ {
qDebug() << "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)
{
_setProp(CV_CAP_PROP_FRAME_WIDTH, res.width());
_setProp(CV_CAP_PROP_FRAME_HEIGHT, res.height());
double w = _getProp(CV_CAP_PROP_FRAME_WIDTH);
double h = _getProp(CV_CAP_PROP_FRAME_HEIGHT);
qDebug() << "PROBING:" << res << " got " << w << h;
resolutions.append(QSize(w,h));
}
unsubscribe();
}
qDebug() << resolutions;
emit resProbingFinished(resolutions);
}
void SelfCamWorker::applyProps()
{
if (!cam.isOpened()) if (!cam.isOpened())
cam.open(camIndex); 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() void SelfCamWorker::doWork()
@ -323,11 +374,15 @@ void SelfCamWorker::doWork()
if (!cam.isOpened()) if (!cam.isOpened())
return; return;
if (qeue.size() > 3)
{
qeue.dequeue();
return;
}
cam >> frame; cam >> frame;
//qDebug() << "Decoding frame"; //qDebug() << "Decoding frame";
mutex.lock(); mutex.lock();
while (qeue.size() > 3)
qeue.dequeue();
qeue.enqueue(frame); qeue.enqueue(frame);
mutex.unlock(); mutex.unlock();
@ -362,3 +417,16 @@ void SelfCamWorker::resume()
{ {
QMetaObject::invokeMethod(this, "_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

@ -21,6 +21,7 @@
#include <QList> #include <QList>
#include <QQueue> #include <QQueue>
#include <QMutex> #include <QMutex>
#include <QMap>
#include "vpx/vpx_image.h" #include "vpx/vpx_image.h"
#include "opencv2/opencv.hpp" #include "opencv2/opencv.hpp"
#include "videosource.h" #include "videosource.h"
@ -42,16 +43,28 @@ public:
void suspend(); void suspend();
void resume(); void resume();
void setProp(int prop, double val);
double getProp(int prop); // blocking call!
void probeResolutions();
public slots: public slots:
void onStart(); void onStart();
signals: signals:
void started();
void newFrameAvailable(); void newFrameAvailable();
void resProbingFinished(QList<QSize> res);
private slots: private slots:
void _suspend(); void _suspend();
void _resume(); void _resume();
void _setProp(int prop, double val);
double _getProp(int prop);
private:
void applyProps();
void subscribe();
void unsubscribe();
private: private:
QMutex mutex; QMutex mutex;
@ -60,17 +73,15 @@ private:
cv::VideoCapture cam; cv::VideoCapture cam;
cv::Mat3b frame; cv::Mat3b frame;
int camIndex; int camIndex;
QMap<int, double> props;
QList<QSize> resolutions;
int refCount;
}; };
class Camera : public VideoSource class Camera : public VideoSource
{ {
Q_OBJECT Q_OBJECT
public: public:
struct VideoMode {
QSize res;
double fps;
};
enum Prop { enum Prop {
BRIGHTNESS, BRIGHTNESS,
SATURATION, SATURATION,
@ -85,11 +96,11 @@ public:
cv::Mat getLastFrame(); ///< Get the last captured frame cv::Mat getLastFrame(); ///< Get the last captured frame
vpx_image getLastVPXImage(); ///< Convert the last frame to a vpx_image (can be expensive !) vpx_image getLastVPXImage(); ///< Convert the last frame to a vpx_image (can be expensive !)
QList<VideoMode> getVideoModes(); QList<QSize> getSupportedResolutions();
VideoMode getBestVideoMode(); QSize getBestVideoMode();
void setVideoMode(VideoMode mode); void setResolution(QSize res);
VideoMode getVideoMode(); QSize getResolution();
void setProp(Prop prop, double val); void setProp(Prop prop, double val);
double getProp(Prop prop); double getProp(Prop prop);
@ -108,18 +119,20 @@ protected:
private: private:
int refcount; ///< Number of users suscribed to the camera int refcount; ///< Number of users suscribed to the camera
cv::VideoCapture cam; ///< OpenCV camera capture opbject
cv::Mat3b currFrame; cv::Mat3b currFrame;
QMutex mutex; QMutex mutex;
VideoMode mode;
QThread* workerThread; QThread* workerThread;
SelfCamWorker* worker; SelfCamWorker* worker;
QList<QSize> resolutions;
static Camera* instance; static Camera* instance;
private slots: private slots:
void onWorkerStarted();
void onNewFrameAvailable(); void onNewFrameAvailable();
void onResProbingFinished(QList<QSize> res);
}; };

View File

@ -28,29 +28,24 @@ AVForm::AVForm() :
camView = new SelfCamView(Camera::getInstance(), this); camView = new SelfCamView(Camera::getInstance(), this);
bodyUI->CamViewLayout->addWidget(camView); bodyUI->CamViewLayout->addWidget(camView);
auto modes = Camera::getInstance()->getVideoModes();
for (Camera::VideoMode m : modes)
{
bodyUI->videoModescomboBox->addItem(QString("%1x%2").arg(QString::number(m.res.width())
,QString::number(m.res.height())));
}
bodyUI->ContrastSlider->setValue(Camera::getInstance()->getProp(Camera::CONTRAST)*100);
bodyUI->BrightnessSlider->setValue(Camera::getInstance()->getProp(Camera::BRIGHTNESS)*100);
bodyUI->SaturationSlider->setValue(Camera::getInstance()->getProp(Camera::SATURATION)*100);
bodyUI->HueSlider->setValue(Camera::getInstance()->getProp(Camera::HUE)*100);
} }
AVForm::~AVForm() AVForm::~AVForm()
{ {
delete bodyUI; delete bodyUI;
} }
#include <QDebug>
void AVForm::show() void AVForm::present()
{ {
qDebug() << "SHADADASDJASLKDJAKLD"; bodyUI->videoModescomboBox->clear();
camView->show(); QList<QSize> res = Camera::getInstance()->getSupportedResolutions();
for (QSize r : res)
bodyUI->videoModescomboBox->addItem(QString("%1x%2").arg(QString::number(r.width()),QString::number(r.height())));
bodyUI->ContrastSlider->setValue(Camera::getInstance()->getProp(Camera::CONTRAST)*100);
bodyUI->BrightnessSlider->setValue(Camera::getInstance()->getProp(Camera::BRIGHTNESS)*100);
bodyUI->SaturationSlider->setValue(Camera::getInstance()->getProp(Camera::SATURATION)*100);
bodyUI->HueSlider->setValue(Camera::getInstance()->getProp(Camera::HUE)*100);
} }
void AVForm::on_ContrastSlider_sliderMoved(int position) void AVForm::on_ContrastSlider_sliderMoved(int position)
@ -79,5 +74,5 @@ void AVForm::on_videoModescomboBox_currentIndexChanged(const QString &arg1)
int w = resStr[0].toInt(); int w = resStr[0].toInt();
int h = resStr[0].toInt(); int h = resStr[0].toInt();
Camera::getInstance()->setVideoMode(Camera::VideoMode{QSize(w,h),60}); Camera::getInstance()->setResolution(QSize(w,h));
} }

View File

@ -35,8 +35,7 @@ class AVForm : public GenericForm
public: public:
AVForm(); AVForm();
~AVForm(); ~AVForm();
virtual void present();
virtual void show();
private slots: private slots: