diff --git a/src/app/avadapter.cpp b/src/app/avadapter.cpp index 8716decc3a76673314ff668cd3ac9b1c1ec19270..c33da472383c29ba6d502f5707b2de6aff33dbe6 100644 --- a/src/app/avadapter.cpp +++ b/src/app/avadapter.cpp @@ -298,8 +298,9 @@ AvAdapter::onAudioDeviceEvent() } void -AvAdapter::onRendererStarted(const QString& id) +AvAdapter::onRendererStarted(const QString& id, const QSize& size) { + Q_UNUSED(size) auto callId = lrcInstance_->getCurrentCallId(); auto callModel = lrcInstance_->getCurrentCallModel(); auto renderDevice = callModel->getCurrentRenderedDevice(callId); diff --git a/src/app/avadapter.h b/src/app/avadapter.h index 793a6f438eccfe655f26e6666eeb6d313fe3cb2c..f565ce59ac82a1669cd24efc03355f39bd33b138 100644 --- a/src/app/avadapter.h +++ b/src/app/avadapter.h @@ -108,7 +108,7 @@ protected: private Q_SLOTS: void onAudioDeviceEvent(); - void onRendererStarted(const QString& id); + void onRendererStarted(const QString& id, const QSize& size); private: // Get screens arrangement rect relative to primary screen. diff --git a/src/app/videoprovider.cpp b/src/app/videoprovider.cpp index 127a8966249d11f2f170b01d3eb78c284e412cc1..ac9ccde79634821b1a9a0021f8fa4c42c03b774c 100644 --- a/src/app/videoprovider.cpp +++ b/src/app/videoprovider.cpp @@ -64,9 +64,17 @@ VideoProvider::registerSink(const QString& id, QVideoSink* obj) if (it == framesObjects_.end()) { auto fo = std::make_unique<FrameObject>(); fo->subscribers.insert(obj); - framesObjects_.emplace(id, std::move(fo)); - return; + qDebug() << "Creating new FrameObject for id:" << id; + auto emplaced = framesObjects_.emplace(id, std::move(fo)); + if (!emplaced.second) { + qWarning() << "Couldn't create FrameObject for id:" << id; + return; + } + it = emplaced.first; } + qDebug().noquote() << QString("Adding sink: 0x%1 to subscribers for id: %2") + .arg((quintptr) obj, QT_POINTER_SIZE * 2, 16, QChar('0')) + .arg(id); it->second->subscribers.insert(obj); } @@ -78,7 +86,11 @@ VideoProvider::unregisterSink(QVideoSink* obj) auto& subs = frameObjIt.second->subscribers; auto it = subs.constFind(obj); if (it != subs.cend()) { + qDebug().noquote() << QString("Removing sink: 0x%1 from subscribers for id: %2") + .arg((quintptr) obj, QT_POINTER_SIZE * 2, 16, QChar('0')) + .arg(frameObjIt.first); subs.erase(it); + return; } } } @@ -121,15 +133,11 @@ VideoProvider::captureVideoFrame(const QString& id) } void -VideoProvider::onRendererStarted(const QString& id) +VideoProvider::onRendererStarted(const QString& id, const QSize& size) { - auto size = avModel_.getRendererSize(id); - // This slot is queued, the renderer may have been destroyed. - if (size.width() == 0 || size.height() == 0 || activeRenderers_[id] == size) { - return; - } - auto pixelFormat = avModel_.useDirectRenderer() ? QVideoFrameFormat::Format_RGBA8888 - : QVideoFrameFormat::Format_BGRA8888; + static const auto pixelFormat = avModel_.useDirectRenderer() + ? QVideoFrameFormat::Format_RGBA8888 + : QVideoFrameFormat::Format_BGRA8888; auto frameFormat = QVideoFrameFormat(size, pixelFormat); { QMutexLocker lk(&framesObjsMutex_); @@ -137,11 +145,11 @@ VideoProvider::onRendererStarted(const QString& id) if (it == framesObjects_.end()) { auto fo = std::make_unique<FrameObject>(); fo->videoFrame = std::make_unique<QVideoFrame>(frameFormat); - qDebug() << "Create new QVideoFrame " << frameFormat.frameSize(); + qDebug() << "Create new QVideoFrame" << frameFormat.frameSize(); framesObjects_.emplace(id, std::move(fo)); } else { it->second->videoFrame.reset(new QVideoFrame(frameFormat)); - qDebug() << "QVideoFrame reset to " << frameFormat.frameSize(); + qDebug() << "QVideoFrame reset to" << frameFormat.frameSize(); } } diff --git a/src/app/videoprovider.h b/src/app/videoprovider.h index c2358a80a27b22b7f879e680c1d22c9b7493f58e..775e425001baf83cad2a10f3e37a7c721018418c 100644 --- a/src/app/videoprovider.h +++ b/src/app/videoprovider.h @@ -48,7 +48,7 @@ public: Q_INVOKABLE QString captureVideoFrame(const QString& id); private Q_SLOTS: - void onRendererStarted(const QString& id); + void onRendererStarted(const QString& id, const QSize& size); void onFrameBufferRequested(const QString& id, AVFrame* avframe); void onFrameUpdated(const QString& id); void onRendererStopped(const QString& id); diff --git a/src/libclient/api/avmodel.h b/src/libclient/api/avmodel.h index 5bcdc5dc4010c71947715df47d898b0d01bc4054..d0ab442e237854d1fe7bced91858750147e497d5 100644 --- a/src/libclient/api/avmodel.h +++ b/src/libclient/api/avmodel.h @@ -281,8 +281,9 @@ Q_SIGNALS: /** * Emitted when a renderer is started * @param id of the renderer + * @param size of the renderer */ - void rendererStarted(const QString& id); + void rendererStarted(const QString& id, const QSize& size); /** * Emitted when a renderer is stopped * @param id of the renderer diff --git a/src/libclient/avmodel.cpp b/src/libclient/avmodel.cpp index 02b8e3f13d3eaff0aa371210c98caba9a4cc0550..dacaf1e076dacc1f7a9a2100e3d05e9bc15fc7bb 100644 --- a/src/libclient/avmodel.cpp +++ b/src/libclient/avmodel.cpp @@ -694,11 +694,13 @@ AVModelPimpl::AVModelPimpl(AVModel& linked, const CallbacksHandler& callbacksHan connect(&callbacksHandler, &CallbacksHandler::decodingStarted, this, - &AVModelPimpl::onDecodingStarted); + &AVModelPimpl::onDecodingStarted, + Qt::DirectConnection); connect(&callbacksHandler, &CallbacksHandler::decodingStopped, this, - &AVModelPimpl::onDecodingStopped); + &AVModelPimpl::onDecodingStopped, + Qt::DirectConnection); auto startedPreview = false; auto restartRenderers = [&](const QStringList& callList) { @@ -750,8 +752,6 @@ AVModelPimpl::getRecordingPath() const void AVModelPimpl::onDecodingStarted(const QString& id, const QString& shmPath, int width, int height) { - if (id != "" && id != "local" && !id.contains("://")) // Else managed by callmodel - return; addRenderer(id, QSize(width, height), shmPath); } @@ -824,41 +824,39 @@ createRenderer(const QString& id, const QSize& res, const QString& shmPath = {}) void AVModelPimpl::addRenderer(const QString& id, const QSize& res, const QString& shmPath) { - { - auto connectRenderer = [this](Renderer* renderer, const QString& id) { - connect( - renderer, - &Renderer::started, - this, - [this, id] { Q_EMIT linked_.rendererStarted(id); }, - Qt::QueuedConnection); - connect( - renderer, - &Renderer::frameBufferRequested, - this, - [this, id](AVFrame* frame) { Q_EMIT linked_.frameBufferRequested(id, frame); }, - Qt::DirectConnection); - connect( - renderer, - &Renderer::frameUpdated, - this, - [this, id] { Q_EMIT linked_.frameUpdated(id); }, - Qt::DirectConnection); - connect( - renderer, - &Renderer::stopped, - this, - [this, id] { Q_EMIT linked_.rendererStopped(id); }, - Qt::DirectConnection); - }; - std::lock_guard<std::mutex> lk(renderers_mtx_); - renderers_.erase(id); // Because it should be done before creating the renderer - auto renderer = createRenderer(id, res, shmPath); - auto& r = renderers_[id]; - r = std::move(renderer); - connectRenderer(r.get(), id); - r->startRendering(); - } + auto connectRenderer = [this](Renderer* renderer, const QString& id) { + connect( + renderer, + &Renderer::started, + this, + [this, id](const QSize& size) { Q_EMIT linked_.rendererStarted(id, size); }, + Qt::DirectConnection); + connect( + renderer, + &Renderer::frameBufferRequested, + this, + [this, id](AVFrame* frame) { Q_EMIT linked_.frameBufferRequested(id, frame); }, + Qt::DirectConnection); + connect( + renderer, + &Renderer::frameUpdated, + this, + [this, id] { Q_EMIT linked_.frameUpdated(id); }, + Qt::DirectConnection); + connect( + renderer, + &Renderer::stopped, + this, + [this, id] { Q_EMIT linked_.rendererStopped(id); }, + Qt::DirectConnection); + }; + std::lock_guard<std::mutex> lk(renderers_mtx_); + renderers_.erase(id); // Because it should be done before creating the renderer + auto renderer = createRenderer(id, res, shmPath); + auto& r = renderers_[id]; + r = std::move(renderer); + connectRenderer(r.get(), id); + r->startRendering(); } void diff --git a/src/libclient/callbackshandler.cpp b/src/libclient/callbackshandler.cpp index 6a93d5124ac7bf16f540bd3bdbfb0bdbf657d976..b0e085d1479f816a68d46e09c4baddd7ecf04caa 100644 --- a/src/libclient/callbackshandler.cpp +++ b/src/libclient/callbackshandler.cpp @@ -275,13 +275,13 @@ CallbacksHandler::CallbacksHandler(const Lrc& parent) &VideoManagerInterface::decodingStarted, this, &CallbacksHandler::decodingStarted, - Qt::QueuedConnection); + Qt::DirectConnection); connect(&VideoManager::instance(), &VideoManagerInterface::decodingStopped, this, &CallbacksHandler::decodingStopped, - Qt::QueuedConnection); + Qt::DirectConnection); connect(&VideoManager::instance(), &VideoManagerInterface::deviceEvent, diff --git a/src/libclient/callmodel.cpp b/src/libclient/callmodel.cpp index 93afd54195cb56ad7e784fc176ead71cb333f959..baf1a19aabf86f63b619d7a1c81bf2f4118075b5 100644 --- a/src/libclient/callmodel.cpp +++ b/src/libclient/callmodel.cpp @@ -253,14 +253,6 @@ public Q_SLOTS: * @param state the new state */ void remoteRecordingChanged(const QString& callId, const QString& peerNumber, bool state); - /** - * Listen from CallbacksHandler when a renderer starts - * @param id - * @param shmPath - * @param width - * @param height - */ - void onDecodingStarted(const QString& id, const QString& shmPath, int width, int height); }; CallModel::CallModel(const account::Info& owner, @@ -525,7 +517,7 @@ CallModel::addMedia(const QString& callId, const QString& source, MediaRequestTy CallManager::instance().requestMediaChange(owner.id, callId, proposedList); callInfo->mediaList = proposedList; if (callInfo->status == call::Status::IN_PROGRESS) - Q_EMIT callInfosChanged(owner.id, callId); + Q_EMIT callInfosChanged(owner.id, callId); } void @@ -578,12 +570,15 @@ CallModel::removeMedia(const QString& callId, return; } else if (!hasVideo) { // To receive the remote video, we need a muted camera - proposedList.push_back( - MapStringString {{MediaAttributeKey::MEDIA_TYPE, MediaAttributeValue::VIDEO}, - {MediaAttributeKey::ENABLED, TRUE_STR}, - {MediaAttributeKey::MUTED, TRUE_STR}, - {MediaAttributeKey::SOURCE, pimpl_->lrc.getAVModel().getCurrentVideoCaptureDevice()}, // not needed to set the source. Daemon should be able to check it - {MediaAttributeKey::LABEL, label.isEmpty() ? "video_0" : label}}); + proposedList.push_back(MapStringString { + {MediaAttributeKey::MEDIA_TYPE, MediaAttributeValue::VIDEO}, + {MediaAttributeKey::ENABLED, TRUE_STR}, + {MediaAttributeKey::MUTED, TRUE_STR}, + {MediaAttributeKey::SOURCE, + pimpl_->lrc.getAVModel() + .getCurrentVideoCaptureDevice()}, // not needed to set the source. Daemon should be + // able to check it + {MediaAttributeKey::LABEL, label.isEmpty() ? "video_0" : label}}); } if (isVideo && !label.isEmpty()) @@ -592,7 +587,7 @@ CallModel::removeMedia(const QString& callId, CallManager::instance().requestMediaChange(owner.id, callId, proposedList); callInfo->mediaList = proposedList; if (callInfo->status == call::Status::IN_PROGRESS) - Q_EMIT callInfosChanged(owner.id, callId); + Q_EMIT callInfosChanged(owner.id, callId); } void @@ -945,10 +940,6 @@ CallModelPimpl::CallModelPimpl(const CallModel& linked, &CallbacksHandler::remoteRecordingChanged, this, &CallModelPimpl::remoteRecordingChanged); - connect(&callbacksHandler, - &CallbacksHandler::decodingStarted, - this, - &CallModelPimpl::onDecodingStarted); #ifndef ENABLE_LIBWRAP // Only necessary with dbus since the daemon runs separately @@ -1644,12 +1635,6 @@ CallModelPimpl::remoteRecordingChanged(const QString& callId, const QString& pee Q_EMIT linked.remoteRecordingChanged(callId, it->second->peerRec, state); } -void -CallModelPimpl::onDecodingStarted(const QString& id, const QString& shmPath, int width, int height) -{ - lrc.getAVModel().addRenderer(id, QSize(width, height), shmPath); -} - } // namespace lrc #include "api/moc_callmodel.cpp" diff --git a/src/libclient/directrenderer.cpp b/src/libclient/directrenderer.cpp index 51209d9b3a90fec19a4d1a847e0cbe5272952e51..6af6d3ba1d5ef315ba9106392b2be9b879acdade 100644 --- a/src/libclient/directrenderer.cpp +++ b/src/libclient/directrenderer.cpp @@ -104,7 +104,7 @@ DirectRenderer::~DirectRenderer() {} void DirectRenderer::startRendering() { - Q_EMIT started(); + Q_EMIT started(size()); } void diff --git a/src/libclient/renderer.h b/src/libclient/renderer.h index 7cba0f9efafdb048a63fe897a378ce0db3b240b0..df7419768058750f58d99189d5229a126ba04229 100644 --- a/src/libclient/renderer.h +++ b/src/libclient/renderer.h @@ -61,7 +61,7 @@ public Q_SLOTS: Q_SIGNALS: void frameUpdated(); void stopped(); - void started(); + void started(const QSize& size); void frameBufferRequested(AVFrame* avFrame); private: diff --git a/src/libclient/shmrenderer.cpp b/src/libclient/shmrenderer.cpp index bdd4eee25087059923732cf68a152be17ca3b681..0a2f9b8922c961186b6481a5f4669aa071c8f12b 100644 --- a/src/libclient/shmrenderer.cpp +++ b/src/libclient/shmrenderer.cpp @@ -328,7 +328,7 @@ ShmRenderer::startRendering() pimpl_->timer->start(); - Q_EMIT started(); + Q_EMIT started(size()); } // Done on destroy instead