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

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

View File

@ -28,29 +28,24 @@ AVForm::AVForm() :
camView = new SelfCamView(Camera::getInstance(), this);
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()
{
delete bodyUI;
}
#include <QDebug>
void AVForm::show()
void AVForm::present()
{
qDebug() << "SHADADASDJASLKDJAKLD";
camView->show();
bodyUI->videoModescomboBox->clear();
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)
@ -79,5 +74,5 @@ void AVForm::on_videoModescomboBox_currentIndexChanged(const QString &arg1)
int w = 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:
AVForm();
~AVForm();
virtual void show();
virtual void present();
private slots: