Skip to content
Snippets Groups Projects
Commit 4909f3fc authored by Stepan Salenikovich's avatar Stepan Salenikovich
Browse files

videorenderermanager: fix renderer lifecycle

The decodingStopped signal is recevied before the call
is in the OVER state most of the time, since its possible
for decoding to start and stop. Thus, once decoding has
stopped, we wait until the call is over to destroy the
renderer.

Change-Id: I440f33a843f657cd9b70ee715a72cae7494a8921
Tuleap: #644
parent 9f223051
No related branches found
No related tags found
No related merge requests found
...@@ -62,13 +62,13 @@ public: ...@@ -62,13 +62,13 @@ public:
//Helper //Helper
void removeRenderer(Video::Renderer* r); void removeRenderer(Video::Renderer* r);
private: private:
VideoRendererManager* q_ptr; VideoRendererManager* q_ptr;
public Q_SLOTS: public Q_SLOTS:
void startedDecoding(const QString& id, const QString& shmPath, int width, int height); void startedDecoding(const QString& id, const QString& shmPath, int width, int height);
void stoppedDecoding(const QString& id, const QString& shmPath); void stoppedDecoding(const QString& id, const QString& shmPath);
void callIsOver();
}; };
...@@ -227,9 +227,9 @@ void VideoRendererManagerPrivate::startedDecoding(const QString& id, const QStri ...@@ -227,9 +227,9 @@ void VideoRendererManagerPrivate::startedDecoding(const QString& id, const QStri
} }
else { else {
r = m_hRenderers[rid]; r = m_hRenderers.value(rid);
QThread* t = m_hThreads[r]; QThread* t = m_hThreads.value(r);
if (t && !t->isRunning()) if (t && !t->isRunning())
t->start(); t->start();
...@@ -280,31 +280,49 @@ void VideoRendererManagerPrivate::startedDecoding(const QString& id, const QStri ...@@ -280,31 +280,49 @@ void VideoRendererManagerPrivate::startedDecoding(const QString& id, const QStri
} }
} }
/// Deletes the renderer and related resources
void VideoRendererManagerPrivate::removeRenderer(Video::Renderer* r)
{
const auto id = m_hRendererIds.value(r);
auto t = m_hThreads.value(r);
m_hRendererIds.remove(r);
m_hRenderers.remove(id);
m_hThreads.remove(r);
if (t) {
t->deleteLater();
}
r->deleteLater();
}
/** /**
* A video stopped being rendered
*
* @warning This method can be called multiple time for the same renderer * @warning This method can be called multiple time for the same renderer
*/ */
void VideoRendererManagerPrivate::removeRenderer(Video::Renderer* r) void VideoRendererManagerPrivate::stoppedDecoding(const QString& id, const QString& shmPath)
{ {
if (!r || !m_hRenderers.contains(m_hRendererIds[r])) Q_UNUSED(shmPath)
return;
const QByteArray id = m_hRendererIds[r];
//Quit if for some reasons the renderer is not found if (!m_hRenderers.contains(id.toLatin1()) || !m_hRenderers.contains(id.toLatin1())) {
if ( !r ) { qWarning() << "Cannot stop decoding, renderer" << id << "not found";
qWarning() << "Cannot stop rendering, renderer" << id << "not found"; return; // nothing to do
return;
} }
auto r = m_hRenderers.value(id.toLatin1());
Call* c = CallModel::instance().getCall(id); Call* c = CallModel::instance().getCall(id);
// TODO: the current implementeation of CallPrivate::removeRenderer() does nothing
if (c && c->lifeCycleState() == Call::LifeCycleState::FINISHED) { if (c && c->lifeCycleState() == Call::LifeCycleState::FINISHED) {
c->d_ptr->removeRenderer(r); c->d_ptr->removeRenderer(r);
} }
r->stopRendering(); r->stopRendering();
qDebug() << "Video stopped for call" << id << "Renderer found:" << m_hRenderers.contains(id); qDebug() << "Video stopped for call" << id << "Renderer found:" << m_hRenderers.contains(id.toLatin1());
Video::Device* dev = Video::DeviceModel::instance().getDevice(id); Video::Device* dev = Video::DeviceModel::instance().getDevice(id);
...@@ -317,34 +335,31 @@ void VideoRendererManagerPrivate::removeRenderer(Video::Renderer* r) ...@@ -317,34 +335,31 @@ void VideoRendererManagerPrivate::removeRenderer(Video::Renderer* r)
emit q_ptr->previewStopped(r); emit q_ptr->previewStopped(r);
} }
QThread* t = m_hThreads[r]; QThread* t = m_hThreads.value(r);
if (t) { if (t) {
t->quit(); t->quit();
t->wait(); t->wait();
} }
// decoding stopped; remove the renderer, if/when call is over
if (c && c->lifeCycleState() == Call::LifeCycleState::FINISHED) { if (c && c->lifeCycleState() == Call::LifeCycleState::FINISHED) {
removeRenderer(r);
m_hRendererIds.remove(r); } else if (c) {
m_hRenderers.remove(id); connect(c, &Call::isOver, this, &VideoRendererManagerPrivate::callIsOver);
m_hThreads[r] = nullptr;
if (t) {
t->deleteLater();
}
r->deleteLater();
} }
} }
///A video stopped being rendered void VideoRendererManagerPrivate::callIsOver()
void VideoRendererManagerPrivate::stoppedDecoding(const QString& id, const QString& shmPath)
{ {
Q_UNUSED(shmPath) if (auto call = qobject_cast<Call *>(sender())) {
if (auto r = m_hRenderers.value(call->dringId().toLatin1()))
if (m_hRenderers.contains(id.toLatin1())) { removeRenderer(r);
removeRenderer(m_hRenderers[id.toLatin1()]); else
qDebug() << "Could not delete renderer, it might have already been removed:" << call->dringId();
// remove the connection from this call to this
disconnect(call, &Call::isOver, this, 0);
} }
} }
......
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Please register or to comment