mirror of
https://gitlab.linphone.org/BC/public/linphone-desktop.git
synced 2026-01-20 13:18:06 +00:00
167 lines
4.7 KiB
C++
167 lines
4.7 KiB
C++
/*
|
|
* CameraPreview.cpp
|
|
* Copyright (C) 2017-2018 Belledonne Communications, Grenoble, France
|
|
*
|
|
* This program is free 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 2
|
|
* 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
|
|
* GNU General Public License for more details.
|
|
*
|
|
* You should have received a copy of the GNU General Public License
|
|
* along with this program; if not, write to the Free Software
|
|
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
|
|
*
|
|
* Created on: April 19, 2017
|
|
* Author: Ronan Abhamon
|
|
*/
|
|
|
|
#include <QOpenGLFramebufferObject>
|
|
#include <QQuickWindow>
|
|
#include <QThread>
|
|
#include <QTimer>
|
|
|
|
#include "components/core/CoreManager.hpp"
|
|
#include "MSFunctions.hpp"
|
|
|
|
#include "CameraPreview.hpp"
|
|
|
|
// =============================================================================
|
|
|
|
using namespace std;
|
|
|
|
namespace {
|
|
constexpr int MaxFps = 30;
|
|
}
|
|
|
|
struct ContextInfo {
|
|
GLuint width;
|
|
GLuint height;
|
|
|
|
OpenGlFunctions *functions;
|
|
};
|
|
|
|
// -----------------------------------------------------------------------------
|
|
|
|
CameraPreviewRenderer::CameraPreviewRenderer () {
|
|
mContextInfo = new ContextInfo();
|
|
}
|
|
|
|
CameraPreviewRenderer::~CameraPreviewRenderer () {
|
|
qInfo() << QStringLiteral("Delete context info:") << mContextInfo;
|
|
|
|
CoreManager *coreManager = CoreManager::getInstance();
|
|
|
|
coreManager->lockVideoRender();
|
|
coreManager->getCore()->setNativePreviewWindowId(nullptr);
|
|
coreManager->unlockVideoRender();
|
|
|
|
delete mContextInfo;
|
|
}
|
|
|
|
QOpenGLFramebufferObject *CameraPreviewRenderer::createFramebufferObject (const QSize &size) {
|
|
QOpenGLFramebufferObjectFormat format;
|
|
format.setAttachment(QOpenGLFramebufferObject::CombinedDepthStencil);
|
|
format.setInternalTextureFormat(GL_RGBA8);
|
|
format.setSamples(4);
|
|
|
|
CoreManager *coreManager = CoreManager::getInstance();
|
|
|
|
// It's not the same thread as render.
|
|
coreManager->lockVideoRender();
|
|
|
|
mContextInfo->width = GLuint(size.width());
|
|
mContextInfo->height = GLuint(size.height());
|
|
mContextInfo->functions = MSFunctions::getInstance()->getFunctions();
|
|
mUpdateContextInfo = true;
|
|
|
|
updateWindowId();
|
|
|
|
coreManager->unlockVideoRender();
|
|
|
|
return new QOpenGLFramebufferObject(size, format);
|
|
}
|
|
|
|
void CameraPreviewRenderer::render () {
|
|
// Draw with ms filter.
|
|
{
|
|
QOpenGLFunctions *f = QOpenGLContext::currentContext()->functions();
|
|
|
|
f->glClearColor(0.f, 0.f, 0.f, 1.f);
|
|
f->glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
|
|
|
|
CoreManager *coreManager = CoreManager::getInstance();
|
|
|
|
coreManager->lockVideoRender();
|
|
MSFunctions *msFunctions = MSFunctions::getInstance();
|
|
msFunctions->bind(f);
|
|
|
|
coreManager->getCore()->previewOglRender();
|
|
|
|
msFunctions->bind(nullptr);
|
|
coreManager->unlockVideoRender();
|
|
}
|
|
|
|
// Synchronize opengl calls with QML.
|
|
if (mWindow)
|
|
mWindow->resetOpenGLState();
|
|
}
|
|
|
|
void CameraPreviewRenderer::synchronize (QQuickFramebufferObject *item) {
|
|
mWindow = item->window();
|
|
}
|
|
|
|
void CameraPreviewRenderer::updateWindowId () {
|
|
if (!mUpdateContextInfo)
|
|
return;
|
|
|
|
mUpdateContextInfo = false;
|
|
|
|
qInfo() << "Thread" << QThread::currentThread() << QStringLiteral("Set context info (width: %1, height: %2):")
|
|
.arg(mContextInfo->width).arg(mContextInfo->height) << mContextInfo;
|
|
|
|
CoreManager::getInstance()->getCore()->setNativePreviewWindowId(mContextInfo);
|
|
}
|
|
|
|
// -----------------------------------------------------------------------------
|
|
|
|
QMutex CameraPreview::mCounterMutex;
|
|
int CameraPreview::mCounter;
|
|
|
|
// -----------------------------------------------------------------------------
|
|
|
|
CameraPreview::CameraPreview (QQuickItem *parent) : QQuickFramebufferObject(parent) {
|
|
mCounterMutex.lock();
|
|
if (++mCounter == 1)
|
|
CoreManager::getInstance()->getCore()->enableVideoPreview(true);
|
|
mCounterMutex.unlock();
|
|
|
|
// The fbo content must be y-mirrored because the ms rendering is y-inverted.
|
|
setMirrorVertically(true);
|
|
|
|
mRefreshTimer = new QTimer(this);
|
|
mRefreshTimer->setInterval(1000 / MaxFps);
|
|
|
|
QObject::connect(
|
|
mRefreshTimer, &QTimer::timeout,
|
|
this, &QQuickFramebufferObject::update,
|
|
Qt::DirectConnection
|
|
);
|
|
|
|
mRefreshTimer->start();
|
|
}
|
|
|
|
CameraPreview::~CameraPreview () {
|
|
mCounterMutex.lock();
|
|
if (--mCounter == 0)
|
|
CoreManager::getInstance()->getCore()->enableVideoPreview(false);
|
|
mCounterMutex.unlock();
|
|
}
|
|
|
|
QQuickFramebufferObject::Renderer *CameraPreview::createRenderer () const {
|
|
return new CameraPreviewRenderer();
|
|
}
|