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:
parent
3e234bd076
commit
200b7bc395
|
@ -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;
|
||||
}
|
||||
|
|
|
@ -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);
|
||||
|
||||
};
|
||||
|
||||
|
|
|
@ -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));
|
||||
}
|
||||
|
|
|
@ -35,8 +35,7 @@ class AVForm : public GenericForm
|
|||
public:
|
||||
AVForm();
|
||||
~AVForm();
|
||||
|
||||
virtual void show();
|
||||
virtual void present();
|
||||
|
||||
private slots:
|
||||
|
||||
|
|
Loading…
Reference in New Issue
Block a user