mirror of
https://github.com/qTox/qTox.git
synced 2024-03-22 14:00:36 +08:00
progress
This commit is contained in:
parent
7f839b473b
commit
3e234bd076
|
@ -1,19 +1,27 @@
|
|||
#ifndef VIDEOSOURCE_H
|
||||
#define VIDEOSOURCE_H
|
||||
|
||||
#include <QObject>
|
||||
#include <QSize>
|
||||
|
||||
class VideoSource
|
||||
class VideoSource : public QObject
|
||||
{
|
||||
Q_OBJECT
|
||||
public:
|
||||
virtual void* getData() = 0;
|
||||
virtual int getDataSize() = 0;
|
||||
virtual void lock() = 0;
|
||||
virtual void* getData() = 0; // a pointer to a frame
|
||||
virtual int getDataSize() = 0; // size of a frame in bytes
|
||||
|
||||
virtual void lock() = 0; // locks a frame so that it can't change
|
||||
virtual void unlock() = 0;
|
||||
virtual QSize resolution() = 0;
|
||||
virtual double fps() = 0;
|
||||
|
||||
virtual QSize resolution() = 0; // resolution of a frame
|
||||
|
||||
virtual void subscribe() = 0;
|
||||
virtual void unsubscribe() = 0;
|
||||
|
||||
signals:
|
||||
void frameAvailable();
|
||||
|
||||
};
|
||||
|
||||
#endif // VIDEOSOURCE_H
|
||||
|
|
|
@ -16,13 +16,35 @@
|
|||
|
||||
#include "camera.h"
|
||||
#include "widget.h"
|
||||
#include <QtConcurrent/QtConcurrentRun>
|
||||
#include <QDebug>
|
||||
#include <QThread>
|
||||
#include <QTimer>
|
||||
|
||||
using namespace cv;
|
||||
Camera* Camera::instance = nullptr;
|
||||
|
||||
Camera::Camera()
|
||||
: refcount{0}
|
||||
: refcount(0)
|
||||
, workerThread(nullptr)
|
||||
, worker(nullptr)
|
||||
{
|
||||
qDebug() << "New Worker";
|
||||
worker = new SelfCamWorker(0);
|
||||
workerThread = new QThread();
|
||||
|
||||
worker->moveToThread(workerThread);
|
||||
|
||||
connect(workerThread, &QThread::started, worker, &SelfCamWorker::onStart);
|
||||
connect(workerThread, &QThread::finished, worker, &SelfCamWorker::deleteLater);
|
||||
connect(workerThread, &QThread::deleteLater, worker, &SelfCamWorker::deleteLater);
|
||||
connect(worker, &SelfCamWorker::newFrameAvailable, this, &Camera::onNewFrameAvailable);
|
||||
workerThread->start();
|
||||
}
|
||||
|
||||
Camera::~Camera()
|
||||
{
|
||||
workerThread->exit();
|
||||
workerThread->deleteLater();
|
||||
}
|
||||
|
||||
void Camera::subscribe()
|
||||
|
@ -30,7 +52,11 @@ void Camera::subscribe()
|
|||
if (refcount <= 0)
|
||||
{
|
||||
refcount = 1;
|
||||
cam.open(0);
|
||||
|
||||
//mode.res.setWidth(cam.get(CV_CAP_PROP_FRAME_WIDTH));
|
||||
//mode.res.setHeight(cam.get(CV_CAP_PROP_FRAME_HEIGHT));
|
||||
|
||||
worker->resume();
|
||||
}
|
||||
else
|
||||
refcount++;
|
||||
|
@ -42,26 +68,22 @@ void Camera::unsubscribe()
|
|||
|
||||
if (refcount <= 0)
|
||||
{
|
||||
//cam.release();
|
||||
worker->suspend();
|
||||
refcount = 0;
|
||||
}
|
||||
}
|
||||
|
||||
Mat Camera::getLastFrame()
|
||||
cv::Mat Camera::getLastFrame()
|
||||
{
|
||||
Mat frame;
|
||||
cv::Mat frame;
|
||||
cam >> frame;
|
||||
|
||||
Mat out;
|
||||
if (!frame.empty())
|
||||
cv::cvtColor(frame, out, CV_BGR2RGB);
|
||||
|
||||
return out;
|
||||
return frame;
|
||||
}
|
||||
|
||||
vpx_image Camera::getLastVPXImage()
|
||||
{
|
||||
Mat3b frame = getLastFrame();
|
||||
cv::Mat3b frame = getLastFrame();
|
||||
vpx_image img;
|
||||
int w = frame.size().width, h = frame.size().height;
|
||||
vpx_img_alloc(&img, VPX_IMG_FMT_I420, w, h, 1); // I420 == YUV420P, same as YV12 with U and V switched
|
||||
|
@ -122,6 +144,7 @@ QList<Camera::VideoMode> Camera::getVideoModes()
|
|||
|
||||
for (QSize res : resolutions)
|
||||
{
|
||||
mutex.lock();
|
||||
cam.set(CV_CAP_PROP_FRAME_WIDTH, res.width());
|
||||
cam.set(CV_CAP_PROP_FRAME_HEIGHT, res.height());
|
||||
|
||||
|
@ -134,6 +157,7 @@ QList<Camera::VideoMode> Camera::getVideoModes()
|
|||
{
|
||||
modes.append({res, 60}); // assume 60fps for now
|
||||
}
|
||||
mutex.unlock();
|
||||
}
|
||||
|
||||
return modes;
|
||||
|
@ -162,10 +186,14 @@ void Camera::setVideoMode(Camera::VideoMode mode)
|
|||
{
|
||||
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());
|
||||
//cam.set(CV_CAP_PROP_SATURATION, 0.5);
|
||||
|
||||
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;
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -210,6 +238,11 @@ double Camera::getProp(Camera::Prop prop)
|
|||
return 0.0;
|
||||
}
|
||||
|
||||
void Camera::onNewFrameAvailable()
|
||||
{
|
||||
emit frameAvailable();
|
||||
}
|
||||
|
||||
void *Camera::getData()
|
||||
{
|
||||
return currFrame.data;
|
||||
|
@ -223,8 +256,12 @@ int Camera::getDataSize()
|
|||
void Camera::lock()
|
||||
{
|
||||
mutex.lock();
|
||||
currFrame = getLastFrame();
|
||||
//getLastFrame().copyTo(currFrame);
|
||||
|
||||
mode.res.setWidth(currFrame.cols);
|
||||
mode.res.setHeight(currFrame.rows);
|
||||
|
||||
if (worker->hasFrame())
|
||||
currFrame = worker->deqeueFrame();
|
||||
}
|
||||
|
||||
void Camera::unlock()
|
||||
|
@ -234,15 +271,94 @@ void Camera::unlock()
|
|||
|
||||
QSize Camera::resolution()
|
||||
{
|
||||
return getVideoMode().res;
|
||||
}
|
||||
|
||||
double Camera::fps()
|
||||
{
|
||||
return getVideoMode().fps;
|
||||
return QSize(currFrame.cols, currFrame.rows);
|
||||
}
|
||||
|
||||
Camera* Camera::getInstance()
|
||||
{
|
||||
return Widget::getInstance()->getCamera();
|
||||
if (!instance)
|
||||
instance = new Camera();
|
||||
|
||||
return instance;
|
||||
}
|
||||
|
||||
// ====================
|
||||
// WORKER
|
||||
// ====================
|
||||
|
||||
SelfCamWorker::SelfCamWorker(int index)
|
||||
: clock(nullptr)
|
||||
, camIndex(index)
|
||||
{
|
||||
}
|
||||
|
||||
void SelfCamWorker::onStart()
|
||||
{
|
||||
clock = new QTimer(this);
|
||||
clock->setSingleShot(false);
|
||||
clock->setInterval(1);
|
||||
|
||||
connect(clock, &QTimer::timeout, this, &SelfCamWorker::doWork);
|
||||
clock->start();
|
||||
|
||||
cam.open(camIndex);
|
||||
}
|
||||
|
||||
void SelfCamWorker::_suspend()
|
||||
{
|
||||
qDebug() << "Suspend";
|
||||
if (cam.isOpened())
|
||||
cam.release();
|
||||
}
|
||||
|
||||
void SelfCamWorker::_resume()
|
||||
{
|
||||
qDebug() << "Resume";
|
||||
if (!cam.isOpened())
|
||||
cam.open(camIndex);
|
||||
}
|
||||
|
||||
void SelfCamWorker::doWork()
|
||||
{
|
||||
if (!cam.isOpened())
|
||||
return;
|
||||
|
||||
cam >> frame;
|
||||
//qDebug() << "Decoding frame";
|
||||
mutex.lock();
|
||||
while (qeue.size() > 3)
|
||||
qeue.dequeue();
|
||||
|
||||
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");
|
||||
}
|
||||
|
|
|
@ -19,6 +19,7 @@
|
|||
|
||||
#include <QImage>
|
||||
#include <QList>
|
||||
#include <QQueue>
|
||||
#include <QMutex>
|
||||
#include "vpx/vpx_image.h"
|
||||
#include "opencv2/opencv.hpp"
|
||||
|
@ -30,8 +31,40 @@
|
|||
* 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();
|
||||
|
||||
public slots:
|
||||
void onStart();
|
||||
|
||||
signals:
|
||||
void newFrameAvailable();
|
||||
|
||||
private slots:
|
||||
void _suspend();
|
||||
void _resume();
|
||||
|
||||
private:
|
||||
QMutex mutex;
|
||||
QQueue<cv::Mat3b> qeue;
|
||||
QTimer* clock;
|
||||
cv::VideoCapture cam;
|
||||
cv::Mat3b frame;
|
||||
int camIndex;
|
||||
};
|
||||
|
||||
class Camera : public VideoSource
|
||||
{
|
||||
Q_OBJECT
|
||||
public:
|
||||
struct VideoMode {
|
||||
QSize res;
|
||||
|
@ -45,10 +78,10 @@ public:
|
|||
HUE,
|
||||
};
|
||||
|
||||
Camera();
|
||||
~Camera();
|
||||
|
||||
static Camera* getInstance(); ///< Returns the global widget's Camera instance
|
||||
virtual void subscribe(); ///< Call this once before trying to get frames
|
||||
virtual void unsubscribe(); ///< Call this once when you don't need frames anymore
|
||||
|
||||
cv::Mat getLastFrame(); ///< Get the last captured frame
|
||||
vpx_image getLastVPXImage(); ///< Convert the last frame to a vpx_image (can be expensive !)
|
||||
|
||||
|
@ -61,20 +94,33 @@ public:
|
|||
void setProp(Prop prop, double val);
|
||||
double getProp(Prop prop);
|
||||
|
||||
private:
|
||||
int refcount; ///< Number of users suscribed to the camera
|
||||
cv::VideoCapture cam; ///< OpenCV camera capture opbject
|
||||
cv::Mat3b currFrame;
|
||||
QMutex mutex;
|
||||
|
||||
// VideoSource interface
|
||||
public:
|
||||
virtual void *getData();
|
||||
virtual int getDataSize();
|
||||
virtual void lock();
|
||||
virtual void unlock();
|
||||
virtual QSize resolution();
|
||||
virtual double fps();
|
||||
virtual void subscribe();
|
||||
virtual void unsubscribe();
|
||||
|
||||
protected:
|
||||
Camera();
|
||||
|
||||
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;
|
||||
|
||||
static Camera* instance;
|
||||
|
||||
private slots:
|
||||
void onNewFrameAvailable();
|
||||
|
||||
};
|
||||
|
||||
#endif // CAMERA_H
|
||||
|
|
|
@ -18,54 +18,59 @@
|
|||
#include "widget/camera.h"
|
||||
#include "ui_avsettings.h"
|
||||
|
||||
AVForm::AVForm(Camera* Cam) :
|
||||
GenericForm(tr("Audio/Video settings"), QPixmap(":/img/settings/av.png")), cam(Cam)
|
||||
AVForm::AVForm() :
|
||||
GenericForm(tr("Audio/Video settings"), QPixmap(":/img/settings/av.png"))
|
||||
{
|
||||
bodyUI = new Ui::AVSettings;
|
||||
bodyUI->setupUi(this);
|
||||
|
||||
cam->subscribe();
|
||||
cam->setVideoMode(cam->getBestVideoMode());
|
||||
camView = new SelfCamView(cam, this);
|
||||
//cam->setVideoMode(cam->getBestVideoMode());
|
||||
camView = new SelfCamView(Camera::getInstance(), this);
|
||||
|
||||
bodyUI->videoGroup->layout()->addWidget(camView);
|
||||
bodyUI->CamViewLayout->addWidget(camView);
|
||||
|
||||
auto modes = cam->getVideoModes();
|
||||
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(cam->getProp(Camera::CONTRAST)*100);
|
||||
bodyUI->BrightnessSlider->setValue(cam->getProp(Camera::BRIGHTNESS)*100);
|
||||
bodyUI->SaturationSlider->setValue(cam->getProp(Camera::SATURATION)*100);
|
||||
bodyUI->HueSlider->setValue(cam->getProp(Camera::HUE)*100);
|
||||
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()
|
||||
{
|
||||
qDebug() << "SHADADASDJASLKDJAKLD";
|
||||
camView->show();
|
||||
}
|
||||
|
||||
void AVForm::on_ContrastSlider_sliderMoved(int position)
|
||||
{
|
||||
cam->setProp(Camera::CONTRAST, position / 100.0);
|
||||
Camera::getInstance()->setProp(Camera::CONTRAST, position / 100.0);
|
||||
}
|
||||
|
||||
void AVForm::on_SaturationSlider_sliderMoved(int position)
|
||||
{
|
||||
cam->setProp(Camera::SATURATION, position / 100.0);
|
||||
Camera::getInstance()->setProp(Camera::SATURATION, position / 100.0);
|
||||
}
|
||||
|
||||
void AVForm::on_BrightnessSlider_sliderMoved(int position)
|
||||
{
|
||||
cam->setProp(Camera::BRIGHTNESS, position / 100.0);
|
||||
Camera::getInstance()->setProp(Camera::BRIGHTNESS, position / 100.0);
|
||||
}
|
||||
|
||||
void AVForm::on_HueSlider_sliderMoved(int position)
|
||||
{
|
||||
cam->setProp(Camera::HUE, position / 100.0);
|
||||
Camera::getInstance()->setProp(Camera::HUE, position / 100.0);
|
||||
}
|
||||
|
||||
void AVForm::on_videoModescomboBox_currentIndexChanged(const QString &arg1)
|
||||
|
@ -74,5 +79,5 @@ void AVForm::on_videoModescomboBox_currentIndexChanged(const QString &arg1)
|
|||
int w = resStr[0].toInt();
|
||||
int h = resStr[0].toInt();
|
||||
|
||||
cam->setVideoMode(Camera::VideoMode{QSize(w,h),60});
|
||||
Camera::getInstance()->setVideoMode(Camera::VideoMode{QSize(w,h),60});
|
||||
}
|
||||
|
|
|
@ -33,24 +33,22 @@ class AVForm : public GenericForm
|
|||
{
|
||||
Q_OBJECT
|
||||
public:
|
||||
AVForm(Camera* cam);
|
||||
AVForm();
|
||||
~AVForm();
|
||||
|
||||
virtual void show();
|
||||
|
||||
private slots:
|
||||
|
||||
void on_ContrastSlider_sliderMoved(int position);
|
||||
void on_SaturationSlider_sliderMoved(int position);
|
||||
void on_BrightnessSlider_sliderMoved(int position);
|
||||
void on_HueSlider_sliderMoved(int position);
|
||||
|
||||
void on_videoModescomboBox_currentIndexChanged(const QString &arg1);
|
||||
|
||||
private:
|
||||
Ui::AVSettings *bodyUI;
|
||||
|
||||
Camera* cam;
|
||||
SelfCamView* camView;
|
||||
|
||||
};
|
||||
|
||||
#endif
|
||||
|
|
|
@ -95,6 +95,16 @@
|
|||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="5" column="1">
|
||||
<layout class="QVBoxLayout" name="CamViewLayout"/>
|
||||
</item>
|
||||
<item row="5" column="0">
|
||||
<widget class="QLabel" name="label_6">
|
||||
<property name="text">
|
||||
<string>Preview</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
</layout>
|
||||
</item>
|
||||
<item>
|
||||
|
|
|
@ -27,7 +27,7 @@ public:
|
|||
GenericForm(const QString &name, const QPixmap &icon) : formName(name), formIcon(icon) {;}
|
||||
~GenericForm() {;}
|
||||
|
||||
virtual void updateContent() {;}
|
||||
virtual void present() {}
|
||||
QString getFormName() {return formName;}
|
||||
QPixmap getFormIcon() {return formIcon;}
|
||||
|
||||
|
|
|
@ -74,7 +74,7 @@ void IdentityForm::onStatusMessageEdited()
|
|||
Core::getInstance()->setStatusMessage(bodyUI->statusMessage->text());
|
||||
}
|
||||
|
||||
void IdentityForm::updateContent()
|
||||
void IdentityForm::present()
|
||||
{
|
||||
toxId->setText(Core::getInstance()->getSelfId().toString());
|
||||
}
|
||||
|
|
|
@ -50,7 +50,7 @@ public:
|
|||
void setUserName(const QString &name);
|
||||
void setStatusMessage(const QString &msg);
|
||||
|
||||
virtual void updateContent();
|
||||
virtual void present();
|
||||
|
||||
signals:
|
||||
void userNameChanged(QString);
|
||||
|
|
|
@ -25,7 +25,7 @@
|
|||
#include <QTabBar>
|
||||
#include <QStackedWidget>
|
||||
|
||||
SettingsWidget::SettingsWidget(Camera* cam, QWidget* parent)
|
||||
SettingsWidget::SettingsWidget(QWidget* parent)
|
||||
: QWidget(parent)
|
||||
{
|
||||
body = new QWidget(this);
|
||||
|
@ -55,7 +55,7 @@ SettingsWidget::SettingsWidget(Camera* cam, QWidget* parent)
|
|||
GeneralForm *gfrm = new GeneralForm;
|
||||
ifrm = new IdentityForm;
|
||||
PrivacyForm *pfrm = new PrivacyForm;
|
||||
AVForm *avfrm = new AVForm(cam);
|
||||
AVForm *avfrm = new AVForm;
|
||||
|
||||
GenericForm *cfgForms[] = {gfrm, ifrm, pfrm, avfrm};
|
||||
for (auto cfgForm : cfgForms)
|
||||
|
@ -85,8 +85,8 @@ void SettingsWidget::show(Ui::MainWindow& ui)
|
|||
void SettingsWidget::onTabChanged(int index)
|
||||
{
|
||||
this->settingsWidgets->setCurrentIndex(index);
|
||||
GenericForm *currentWidget = static_cast<GenericForm*>(this->settingsWidgets->widget(index));
|
||||
currentWidget->updateContent();
|
||||
GenericForm* currentWidget = static_cast<GenericForm*>(this->settingsWidgets->widget(index));
|
||||
currentWidget->present();
|
||||
nameLabel->setText(currentWidget->getFormName());
|
||||
imgLabel->setPixmap(currentWidget->getFormIcon().scaledToHeight(40, Qt::SmoothTransformation));
|
||||
}
|
||||
|
|
|
@ -35,7 +35,7 @@ class SettingsWidget : public QWidget
|
|||
{
|
||||
Q_OBJECT
|
||||
public:
|
||||
SettingsWidget(Camera* cam, QWidget* parent = nullptr);
|
||||
SettingsWidget(QWidget* parent = nullptr);
|
||||
~SettingsWidget();
|
||||
|
||||
void show(Ui::MainWindow &ui);
|
||||
|
|
|
@ -29,13 +29,11 @@ SelfCamView::SelfCamView(VideoSource *Source, QWidget* parent)
|
|||
, program(nullptr)
|
||||
, textureId(0)
|
||||
, pboAllocSize(0)
|
||||
, useNewFrame(false)
|
||||
, hasSubscribed(false)
|
||||
{
|
||||
source->subscribe();
|
||||
|
||||
qDebug()<<"NEW:"<<source->resolution();
|
||||
qDebug()<<"NEW VideoSurface:"<<source->resolution();
|
||||
setFixedSize(source->resolution());
|
||||
|
||||
|
||||
}
|
||||
|
||||
SelfCamView::~SelfCamView()
|
||||
|
@ -49,21 +47,38 @@ SelfCamView::~SelfCamView()
|
|||
source->unsubscribe();
|
||||
}
|
||||
|
||||
void SelfCamView::hideEvent(QHideEvent *ev)
|
||||
{
|
||||
if (hasSubscribed)
|
||||
{
|
||||
source->unsubscribe();
|
||||
hasSubscribed = false;
|
||||
disconnect(source, &VideoSource::frameAvailable, this, &SelfCamView::updateGL);
|
||||
}
|
||||
|
||||
QGLWidget::hideEvent(ev);
|
||||
}
|
||||
|
||||
void SelfCamView::showEvent(QShowEvent *ev)
|
||||
{
|
||||
if (!hasSubscribed)
|
||||
{
|
||||
source->subscribe();
|
||||
hasSubscribed = true;
|
||||
connect(source, &VideoSource::frameAvailable, this, &SelfCamView::updateGL);
|
||||
}
|
||||
|
||||
QGLWidget::showEvent(ev);
|
||||
}
|
||||
|
||||
void SelfCamView::initializeGL()
|
||||
{
|
||||
updateTimer = new QTimer(this);
|
||||
updateTimer->setSingleShot(false);
|
||||
updateTimer->setInterval(1000.0 / source->fps());
|
||||
|
||||
connect(updateTimer, &QTimer::timeout, this, &SelfCamView::update);
|
||||
updateTimer->start();
|
||||
}
|
||||
|
||||
void SelfCamView::paintGL()
|
||||
{
|
||||
source->lock();
|
||||
void* frame = source->getData();
|
||||
int frameBytes = source->getDataSize();
|
||||
//qDebug() << "PainterThread" << QThread::currentThreadId();
|
||||
|
||||
if (!pbo)
|
||||
{
|
||||
|
@ -87,7 +102,8 @@ void SelfCamView::paintGL()
|
|||
"uniform sampler2D texture0;"
|
||||
"varying vec2 coords;"
|
||||
"void main() {"
|
||||
" gl_FragColor = texture2D(texture0,coords*vec2(1.0, -1.0));"
|
||||
" vec4 color = texture2D(texture0,coords*vec2(1.0, -1.0));"
|
||||
" gl_FragColor = vec4(color.b, color.g, color.r, 1);"
|
||||
"}");
|
||||
|
||||
program->bindAttributeLocation("vertices", 0);
|
||||
|
@ -108,30 +124,42 @@ void SelfCamView::paintGL()
|
|||
setFixedSize(res);
|
||||
}
|
||||
|
||||
if (pboAllocSize != frameBytes)
|
||||
|
||||
if (useNewFrame)
|
||||
{
|
||||
qDebug() << "Resize pbo " << frameBytes << "bytes (was" << pboAllocSize << ") res " << source->resolution();
|
||||
source->lock();
|
||||
void* frame = source->getData();
|
||||
int frameBytes = source->getDataSize();
|
||||
|
||||
if (pboAllocSize != frameBytes && frameBytes > 0)
|
||||
{
|
||||
qDebug() << "Resize pbo " << frameBytes << "bytes (was" << pboAllocSize << ") res " << source->resolution();
|
||||
|
||||
pbo->bind();
|
||||
pbo->allocate(frameBytes);
|
||||
pbo->release();
|
||||
|
||||
pboAllocSize = frameBytes;
|
||||
}
|
||||
|
||||
// transfer data
|
||||
pbo->bind();
|
||||
pbo->allocate(frameBytes);
|
||||
|
||||
void* ptr = pbo->map(QOpenGLBuffer::WriteOnly);
|
||||
if (ptr && frame)
|
||||
memcpy(ptr, frame, frameBytes);
|
||||
pbo->unmap();
|
||||
|
||||
source->unlock();
|
||||
|
||||
//transfer pbo data to texture
|
||||
glBindTexture(GL_TEXTURE_2D, textureId);
|
||||
glTexSubImage2D(GL_TEXTURE_2D,0,0,0, res.width(), res.height(), GL_RGB, GL_UNSIGNED_BYTE, 0);
|
||||
glBindTexture(GL_TEXTURE_2D, 0);
|
||||
|
||||
pbo->release();
|
||||
|
||||
pboAllocSize = frameBytes;
|
||||
}
|
||||
|
||||
// transfer data
|
||||
pbo->bind();
|
||||
|
||||
void* ptr = pbo->map(QOpenGLBuffer::WriteOnly);
|
||||
if (ptr)
|
||||
memcpy(ptr, frame, frameBytes);
|
||||
pbo->unmap();
|
||||
|
||||
//transfer pbo data to texture
|
||||
glBindTexture(GL_TEXTURE_2D, textureId);
|
||||
glTexSubImage2D(GL_TEXTURE_2D,0,0,0, res.width(), res.height(), GL_RGB, GL_UNSIGNED_BYTE, 0);
|
||||
glBindTexture(GL_TEXTURE_2D, 0);
|
||||
|
||||
// render pbo
|
||||
float values[] = {
|
||||
-1, -1,
|
||||
|
@ -155,18 +183,20 @@ void SelfCamView::paintGL()
|
|||
|
||||
//draw fullscreen quad
|
||||
glDrawArrays(GL_TRIANGLE_STRIP, 0, 4);
|
||||
glBindTexture(GL_TEXTURE_2D, 0);
|
||||
|
||||
program->disableAttributeArray(0);
|
||||
program->release();
|
||||
|
||||
pbo->release();
|
||||
//glFlush();
|
||||
|
||||
source->unlock();
|
||||
useNewFrame = false;
|
||||
}
|
||||
|
||||
void SelfCamView::update()
|
||||
void SelfCamView::updateGL()
|
||||
{
|
||||
QGLWidget::update();
|
||||
useNewFrame = true;
|
||||
QGLWidget::updateGL();
|
||||
}
|
||||
|
||||
|
||||
|
|
|
@ -32,10 +32,14 @@ public:
|
|||
SelfCamView(VideoSource* source, QWidget* parent=0);
|
||||
~SelfCamView();
|
||||
|
||||
virtual void hideEvent(QHideEvent* ev);
|
||||
virtual void showEvent(QShowEvent* ev);
|
||||
|
||||
// QGLWidget interface
|
||||
protected:
|
||||
virtual void initializeGL();
|
||||
virtual void paintGL();
|
||||
virtual void updateGL();
|
||||
|
||||
void update();
|
||||
|
||||
|
@ -43,10 +47,12 @@ private:
|
|||
VideoSource* source;
|
||||
QOpenGLBuffer* pbo;
|
||||
QOpenGLShaderProgram* program;
|
||||
QTimer* updateTimer;
|
||||
GLuint textureId;
|
||||
int pboAllocSize;
|
||||
QSize res;
|
||||
bool useNewFrame;
|
||||
bool hasSubscribed;
|
||||
|
||||
};
|
||||
|
||||
#endif // SELFCAMVIEW_H
|
||||
|
|
|
@ -100,8 +100,7 @@ Widget::Widget(QWidget *parent)
|
|||
ui->statusButton->setProperty("status", "offline");
|
||||
Style::repolish(ui->statusButton);
|
||||
|
||||
camera = new Camera;
|
||||
settingsWidget = new SettingsWidget(camera);
|
||||
settingsWidget = new SettingsWidget();
|
||||
|
||||
// Disable some widgets until we're connected to the DHT
|
||||
ui->statusButton->setEnabled(false);
|
||||
|
@ -117,7 +116,7 @@ Widget::Widget(QWidget *parent)
|
|||
qRegisterMetaType<ToxFile::FileDirection>("ToxFile::FileDirection");
|
||||
|
||||
coreThread = new QThread(this);
|
||||
core = new Core(camera, coreThread);
|
||||
core = new Core(Camera::getInstance(), coreThread);
|
||||
core->moveToThread(coreThread);
|
||||
connect(coreThread, &QThread::started, core, &Core::start);
|
||||
|
||||
|
@ -215,11 +214,6 @@ QString Widget::getUsername()
|
|||
return core->getUsername();
|
||||
}
|
||||
|
||||
Camera* Widget::getCamera()
|
||||
{
|
||||
return camera;
|
||||
}
|
||||
|
||||
void Widget::onAvatarClicked()
|
||||
{
|
||||
QString filename = QFileDialog::getOpenFileName(this, tr("Choose a profile picture"), QDir::homePath());
|
||||
|
|
|
@ -122,7 +122,6 @@ private:
|
|||
static Widget* instance;
|
||||
GenericChatroomWidget* activeChatroomWidget;
|
||||
FriendListWidget* contactListWidget;
|
||||
Camera* camera;
|
||||
MaskablePixmapWidget* profilePicture;
|
||||
bool notify(QObject *receiver, QEvent *event);
|
||||
};
|
||||
|
|
Loading…
Reference in New Issue
Block a user