Skip to content
Snippets Groups Projects
Commit 76f03877 authored by Emmanuel Lepage Vallee's avatar Emmanuel Lepage Vallee Committed by Guillaume Roguez
Browse files

video: Use a thread pool instead of two theads


It now use a thread per renderer. It is now easier to manage
the renderers lifecycles.

Refs #69137

Signed-off-by: default avatarGuillaume Roguez <guillaume.roguez@savoirfairelinux.com>
parent 99a88d80
No related branches found
No related tags found
No related merge requests found
......@@ -18,31 +18,32 @@
***************************************************************************/
#include "videorenderermanager.h"
//libstdc++
#include <vector>
//Qt
#include <QtCore/QMutex>
//Ring
#include "../dbus/videomanager.h"
#include "video/device.h"
#include <dbus/videomanager.h>
#include <video/device.h>
#include <call.h>
#include <callmodel.h>
#include "video/renderer.h"
#include "video/devicemodel.h"
#include "video/channel.h"
#include "video/rate.h"
#include "video/resolution.h"
#include <video/renderer.h>
#include <video/devicemodel.h>
#include <video/channel.h>
#include <video/rate.h>
#include <video/resolution.h>
#include "private/videorate_p.h"
#include "private/call_p.h"
#if defined(Q_OS_DARWIN)
#include "private/directrenderer.h"
#ifdef ENABLE_LIBWRAP
#include "private/directrenderer.h"
#else
#include "private/shmrenderer.h"
#include "private/shmrenderer.h"
#endif
constexpr static const char LOCAL_DEVICE[] = "local";
constexpr static const char PREVIEW_RENDERER_ID[] = "local";
//Static member
VideoRendererManager* VideoRendererManager::m_spInstance = nullptr;
......@@ -55,9 +56,11 @@ public:
VideoRendererManagerPrivate(VideoRendererManager* parent);
//Attributes
bool m_PreviewState;
uint m_BufferSize ;
QHash<QByteArray,Video::Renderer*> m_lRenderers;
bool m_PreviewState;
uint m_BufferSize ;
QHash<QByteArray,Video::Renderer*> m_hRenderers ;
QHash<Video::Renderer*, QThread*> m_hThreads ;
private:
VideoRendererManager* q_ptr;
......@@ -65,7 +68,6 @@ private:
public Q_SLOTS:
void startedDecoding(const QString& id, const QString& shmPath, int width, int height);
void stoppedDecoding(const QString& id, const QString& shmPath);
void deviceEvent();
};
......@@ -76,10 +78,9 @@ m_BufferSize(0),m_PreviewState(false)
}
///Constructor
VideoRendererManager::VideoRendererManager():QThread(), d_ptr(new VideoRendererManagerPrivate(this))
VideoRendererManager::VideoRendererManager():QObject(QCoreApplication::instance()), d_ptr(new VideoRendererManagerPrivate(this))
{
VideoManagerInterface& interface = DBus::VideoManager::instance();
connect( &interface , SIGNAL(deviceEvent()) , d_ptr.data(), SLOT(deviceEvent()) );
connect( &interface , &VideoManagerInterface::startedDecoding, d_ptr.data(), &VideoRendererManagerPrivate::startedDecoding);
connect( &interface , &VideoManagerInterface::stoppedDecoding, d_ptr.data(), &VideoRendererManagerPrivate::stoppedDecoding);
}
......@@ -96,6 +97,7 @@ VideoRendererManager* VideoRendererManager::instance()
if (!m_spInstance) {
m_spInstance = new VideoRendererManager();
}
return m_spInstance;
}
......@@ -103,13 +105,15 @@ VideoRendererManager* VideoRendererManager::instance()
Video::Renderer* VideoRendererManager::getRenderer(const Call* call) const
{
if (!call) return nullptr;
return d_ptr->m_lRenderers[call->dringId().toLatin1()];
return d_ptr->m_hRenderers[call->dringId().toLatin1()];
}
///Get the video preview Renderer
Video::Renderer* VideoRendererManager::previewRenderer()
{
if (!d_ptr->m_lRenderers[LOCAL_DEVICE]) {
if (!d_ptr->m_hRenderers[PREVIEW_RENDERER_ID]) {
if ((!Video::DeviceModel::instance()->activeDevice()) || (!Video::DeviceModel::instance()->activeDevice()->activeChannel())) {
qWarning() << "No device found";
return nullptr;
......@@ -122,33 +126,46 @@ Video::Renderer* VideoRendererManager::previewRenderer()
return nullptr;
}
#if defined(Q_OS_DARWIN)
d_ptr->m_lRenderers[LOCAL_DEVICE] = new Video::DirectRenderer(LOCAL_DEVICE, res->size());
#else
d_ptr->m_lRenderers[LOCAL_DEVICE] = new Video::ShmRenderer(LOCAL_DEVICE,"",res->size());
Video::Renderer* r = nullptr;
#ifdef ENABLE_LIBWRAP
r = new Video::DirectRenderer(PREVIEW_RENDERER_ID, res->size());
#else //ENABLE_LIBWRAP
r = new Video::ShmRenderer(PREVIEW_RENDERER_ID,"",res->size());
#endif
QThread* t = new QThread(this);
d_ptr->m_hThreads[r] = t;
r->moveToThread(t);
d_ptr->m_hRenderers[PREVIEW_RENDERER_ID] = r;
}
return d_ptr->m_lRenderers[LOCAL_DEVICE];
return d_ptr->m_hRenderers[PREVIEW_RENDERER_ID];
}
///Stop video preview
void VideoRendererManager::stopPreview()
{
//d_ptr->stoppedDecoding(LOCAL_DEVICE,"");
VideoManagerInterface& interface = DBus::VideoManager::instance();
interface.stopCamera();
DBus::VideoManager::instance().stopCamera();
d_ptr->m_PreviewState = false;
}
///Start video preview
void VideoRendererManager::startPreview()
{
// d_ptr->startedDecoding(LOCAL_DEVICE,"",500,500);
if (d_ptr->m_PreviewState) return;
VideoManagerInterface& interface = DBus::VideoManager::instance();
interface.startCamera();
if (d_ptr->m_PreviewState)
return;
DBus::VideoManager::instance().startCamera();
d_ptr->m_PreviewState = true;
}
///Is the video model fetching preview from a camera
......@@ -163,63 +180,87 @@ void VideoRendererManager::setBufferSize(uint size)
d_ptr->m_BufferSize = size;
}
///Event callback
void VideoRendererManagerPrivate::deviceEvent()
{
//TODO is there anything useful to do?
}
///A video is not being rendered
void VideoRendererManagerPrivate::startedDecoding(const QString& id, const QString& shmPath, int width, int height)
{
const QSize res = QSize(width,height);
const QSize res = QSize(width,height);
const QByteArray rid = id.toLatin1();
qWarning() << "startedDecoding for sink id: " << id;
if (m_lRenderers[rid] == nullptr ) {
#if defined(Q_OS_DARWIN)
m_lRenderers[rid] = new Video::DirectRenderer(rid, res);
Video::Renderer* r = m_hRenderers[rid];
if (r == nullptr ) {
#ifdef ENABLE_LIBWRAP
r = new Video::DirectRenderer(rid, res);
qWarning() << "Calling registerFrameListener";
DBus::VideoManager::instance().registerSinkTarget(id, [this, id, width, height] (const unsigned char* frame) {
static_cast<Video::DirectRenderer*>(m_lRenderers[id.toLatin1()])->onNewFrame(
QByteArray::fromRawData(reinterpret_cast<const char *>(frame), width*height));
static_cast<Video::DirectRenderer*>(m_hRenderers[id.toLatin1()])->onNewFrame(
QByteArray::fromRawData(reinterpret_cast<const char *>(frame), width*height)
);
});
#else
m_lRenderers[rid] = new Video::ShmRenderer(rid,shmPath,res);
#else //ENABLE_LIBWRAP
r = new Video::ShmRenderer(rid,shmPath,res);
#endif
m_lRenderers[rid]->moveToThread(q_ptr);
if (!q_ptr->isRunning())
q_ptr->start();
m_hRenderers[rid] = r;
QThread* t = new QThread(this);
m_hThreads[r] = t;
r->moveToThread(t);
if (!t->isRunning())
t->start();
}
else {
m_lRenderers[rid]->setSize(res);
r->setSize(res);
#ifdef ENABLE_LIBWRAP
DBus::VideoManager::instance().registerSinkTarget(id, [this, id, width, height] (const unsigned char* frame) {
static_cast<Video::DirectRenderer*>(m_lRenderers[id.toLatin1()])->onNewFrame(
QByteArray::fromRawData(reinterpret_cast<const char *>(frame), width*height));
static_cast<Video::DirectRenderer*>(m_hRenderers[id.toLatin1()])->onNewFrame(
QByteArray::fromRawData(reinterpret_cast<const char *>(frame), width*height)
);
});
#endif
#if !defined(Q_OS_DARWIN)
static_cast<Video::ShmRenderer*>(m_lRenderers[rid])->setShmPath(shmPath);
#else //ENABLE_LIBWRAP
static_cast<Video::ShmRenderer*>(r)->setShmPath(shmPath);
#endif
}
m_lRenderers[rid]->startRendering();
r->startRendering();
Video::Device* dev = Video::DeviceModel::instance()->getDevice(id);
if (dev) {
emit dev->renderingStarted(m_lRenderers[rid]);
}
if (id != LOCAL_DEVICE) {
if (dev)
emit dev->renderingStarted(r);
if (id != PREVIEW_RENDERER_ID) {
qDebug() << "Starting video for call" << id;
Call* c = CallModel::instance()->getCall(id);
if (c)
c->d_ptr->registerRenderer(m_lRenderers[rid]);
c->d_ptr->registerRenderer(r);
}
else {
m_PreviewState = true;
emit q_ptr->previewStateChanged(true);
emit q_ptr->previewStarted(m_lRenderers[rid]);
emit q_ptr->previewStarted(r);
}
}
......@@ -227,25 +268,35 @@ void VideoRendererManagerPrivate::startedDecoding(const QString& id, const QStri
void VideoRendererManagerPrivate::stoppedDecoding(const QString& id, const QString& shmPath)
{
Q_UNUSED(shmPath)
Video::Renderer* r = m_lRenderers[id.toLatin1()];
if ( r ) {
Video::Renderer* r = m_hRenderers[id.toLatin1()];
if ( r )
r->stopRendering();
}
qDebug() << "Video stopped for call" << id << "Renderer found:" << (m_lRenderers[id.toLatin1()] != nullptr);
qDebug() << "Video stopped for call" << id << "Renderer found:" << (m_hRenderers[id.toLatin1()] != nullptr);
// emit videoStopped();
Video::Device* dev = Video::DeviceModel::instance()->getDevice(id);
if (dev) {
if (dev)
emit dev->renderingStopped(r);
}
if (id == LOCAL_DEVICE) {
if (id == PREVIEW_RENDERER_ID) {
m_PreviewState = false;
emit q_ptr->previewStateChanged(false);
emit q_ptr->previewStopped(r);
}
// r->mutex()->lock();
m_lRenderers[id.toLatin1()] = nullptr;
m_hRenderers[id.toLatin1()] = nullptr;
QThread* t = m_hThreads[r];
m_hThreads[r] = nullptr;
t->quit();
t->wait();
delete r;
t->deleteLater();
}
void VideoRendererManager::switchDevice(const Video::Device* device) const
......
......@@ -37,7 +37,7 @@ struct SHMHeader;
class VideoRendererManagerPrivate;
///VideoModel: Video event dispatcher
class VideoRendererManager : public QThread {
class VideoRendererManager : public QObject {
#pragma GCC diagnostic push
#pragma GCC diagnostic ignored "-Wzero-as-null-pointer-constant"
Q_OBJECT
......
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment