Commit 9f1fc6df authored by Ronan Abhamon's avatar Ronan Abhamon

fix(src/components/camera/Camera): deal with multi-threads

parent b1f294f5
...@@ -27,6 +27,7 @@ ...@@ -27,6 +27,7 @@
#include "Camera.hpp" #include "Camera.hpp"
#include <QFileInfo> #include <QFileInfo>
#include <QThread>
#include <QQuickWindow> #include <QQuickWindow>
// ============================================================================= // =============================================================================
...@@ -48,6 +49,9 @@ struct CameraStateBinder { ...@@ -48,6 +49,9 @@ struct CameraStateBinder {
f->glDisable(GL_CULL_FACE); f->glDisable(GL_CULL_FACE);
f->glDisable(GL_DEPTH_TEST); f->glDisable(GL_DEPTH_TEST);
// Process at next tick.
m_renderer->update();
} }
CameraRenderer *m_renderer; CameraRenderer *m_renderer;
...@@ -78,21 +82,27 @@ QOpenGLFramebufferObject *CameraRenderer::createFramebufferObject (const QSize & ...@@ -78,21 +82,27 @@ QOpenGLFramebufferObject *CameraRenderer::createFramebufferObject (const QSize &
format.setInternalTextureFormat(GL_RGBA8); format.setInternalTextureFormat(GL_RGBA8);
format.setSamples(4); format.setSamples(4);
CoreManager *core = CoreManager::getInstance();
core->lockVideoRender();
m_context_info->width = size.width(); m_context_info->width = size.width();
m_context_info->height = size.height(); m_context_info->height = size.height();
m_context_info->functions = MSFunctions::getInstance()->getFunctions(); m_context_info->functions = MSFunctions::getInstance()->getFunctions();
m_need_sync = true; updateWindowId();
core->unlockVideoRender();
return new QOpenGLFramebufferObject(size, format); return new QOpenGLFramebufferObject(size, format);
} }
void CameraRenderer::render () { void CameraRenderer::render () {
CameraStateBinder state(this);
if (!m_linphone_call) if (!m_linphone_call)
return; return;
CameraStateBinder state(this);
// Draw with ms filter. // Draw with ms filter.
{ {
QOpenGLFunctions *f = QOpenGLContext::currentContext()->functions(); QOpenGLFunctions *f = QOpenGLContext::currentContext()->functions();
...@@ -115,38 +125,27 @@ void CameraRenderer::render () { ...@@ -115,38 +125,27 @@ void CameraRenderer::render () {
// Synchronize opengl calls with QML. // Synchronize opengl calls with QML.
if (m_window) if (m_window)
m_window->resetOpenGLState(); m_window->resetOpenGLState();
// Process at next tick.
update();
} }
void CameraRenderer::synchronize (QQuickFramebufferObject *item) { void CameraRenderer::synchronize (QQuickFramebufferObject *item) {
m_window = item->window(); m_window = item->window();
if (!m_need_sync) { Camera *camera = qobject_cast<Camera *>(item);
Camera *camera = qobject_cast<Camera *>(item);
shared_ptr<linphone::Call> linphone_call = camera->getCall()->getLinphoneCall();
bool is_preview = camera->m_is_preview;
if (m_linphone_call == linphone_call && m_is_preview == is_preview) m_linphone_call = camera->getCall()->getLinphoneCall();
return; m_is_preview = camera->m_is_preview;
m_linphone_call = linphone_call; updateWindowId();
m_is_preview = is_preview; }
}
m_need_sync = false;
qInfo() << QStringLiteral("Set context info (width: %1, height: %2, is_preview: %3).") void CameraRenderer::updateWindowId () {
qInfo() << "Thread" << QThread::currentThread() << QStringLiteral("Set context info (width: %1, height: %2, is_preview: %3).")
.arg(m_context_info->width).arg(m_context_info->height).arg(m_is_preview); .arg(m_context_info->width).arg(m_context_info->height).arg(m_is_preview);
void *window_id = const_cast<ContextInfo *>(m_context_info);
if (m_is_preview) if (m_is_preview)
CoreManager::getInstance()->getCore()->setNativePreviewWindowId(window_id); CoreManager::getInstance()->getCore()->setNativePreviewWindowId(m_context_info);
else else if (m_linphone_call)
m_linphone_call->setNativeVideoWindowId(window_id); m_linphone_call->setNativeVideoWindowId(m_context_info);
} }
// ----------------------------------------------------------------------------- // -----------------------------------------------------------------------------
...@@ -159,25 +158,10 @@ Camera::Camera (QQuickItem *parent) : QQuickFramebufferObject(parent) { ...@@ -159,25 +158,10 @@ Camera::Camera (QQuickItem *parent) : QQuickFramebufferObject(parent) {
setMirrorVertically(true); setMirrorVertically(true);
} }
Camera::~Camera () {
CoreManager *core = CoreManager::getInstance();
core->lockVideoRender();
if (m_is_preview)
CoreManager::getInstance()->getCore()->setNativePreviewWindowId(nullptr);
else
m_call->getLinphoneCall()->setNativeVideoWindowId(nullptr);
core->unlockVideoRender();
}
QQuickFramebufferObject::Renderer *Camera::createRenderer () const { QQuickFramebufferObject::Renderer *Camera::createRenderer () const {
return new CameraRenderer(); return new CameraRenderer();
} }
// -----------------------------------------------------------------------------
void Camera::mousePressEvent (QMouseEvent *) { void Camera::mousePressEvent (QMouseEvent *) {
setFocus(true); setFocus(true);
} }
...@@ -191,7 +175,21 @@ CallModel *Camera::getCall () const { ...@@ -191,7 +175,21 @@ CallModel *Camera::getCall () const {
void Camera::setCall (CallModel *call) { void Camera::setCall (CallModel *call) {
if (m_call != call) { if (m_call != call) {
m_call = call; m_call = call;
update();
emit callChanged(m_call); emit callChanged(m_call);
} }
} }
bool Camera::getIsPreview () const {
return m_is_preview;
}
void Camera::setIsPreview (bool status) {
if (m_is_preview != status) {
m_is_preview = status;
update();
emit isPreviewChanged(status);
}
}
...@@ -35,6 +35,7 @@ struct ContextInfo; ...@@ -35,6 +35,7 @@ struct ContextInfo;
class CameraRenderer : public QQuickFramebufferObject::Renderer { class CameraRenderer : public QQuickFramebufferObject::Renderer {
friend class Camera; friend class Camera;
friend struct CameraStateBinder;
public: public:
CameraRenderer (); CameraRenderer ();
...@@ -46,8 +47,9 @@ protected: ...@@ -46,8 +47,9 @@ protected:
void synchronize (QQuickFramebufferObject *item) override; void synchronize (QQuickFramebufferObject *item) override;
private: private:
void updateWindowId ();
ContextInfo *m_context_info; ContextInfo *m_context_info;
bool m_need_sync = false;
bool m_is_preview = false; bool m_is_preview = false;
shared_ptr<linphone::Call> m_linphone_call; shared_ptr<linphone::Call> m_linphone_call;
...@@ -63,11 +65,11 @@ class Camera : public QQuickFramebufferObject { ...@@ -63,11 +65,11 @@ class Camera : public QQuickFramebufferObject {
Q_OBJECT; Q_OBJECT;
Q_PROPERTY(CallModel * call READ getCall WRITE setCall NOTIFY callChanged); Q_PROPERTY(CallModel * call READ getCall WRITE setCall NOTIFY callChanged);
Q_PROPERTY(bool isPreview MEMBER m_is_preview NOTIFY isPreviewChanged); Q_PROPERTY(bool isPreview READ getIsPreview WRITE setIsPreview NOTIFY isPreviewChanged);
public: public:
Camera (QQuickItem *parent = Q_NULLPTR); Camera (QQuickItem *parent = Q_NULLPTR);
~Camera (); ~Camera () = default;
QQuickFramebufferObject::Renderer *createRenderer () const override; QQuickFramebufferObject::Renderer *createRenderer () const override;
...@@ -82,6 +84,9 @@ private: ...@@ -82,6 +84,9 @@ private:
CallModel *getCall () const; CallModel *getCall () const;
void setCall (CallModel *call); void setCall (CallModel *call);
bool getIsPreview () const;
void setIsPreview (bool status);
bool m_is_preview = false; bool m_is_preview = false;
CallModel *m_call = nullptr; CallModel *m_call = nullptr;
}; };
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment