From fb1c65ac24cf97dbe0ee321529c369140fffeb5f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?I=C3=B1aki=20Baz=20Castillo?= Date: Fri, 4 Nov 2022 10:29:27 +0100 Subject: [PATCH 1/6] ActiveSpeakerObserver: fix memory leak and more improvements - When deleted, `ActiveSpeakerObserver` must iterate all entries in its `mapProducerSpeakers` and free them. This is because `ActiveSpeakerObserver::RemoveProducer()` **won't** be called for each existing `Producer` if the `ActiveSpeakerObserver` or its parent `Router` are directly closed. - If `AddProducer()` is called with an already paused `Producer`, consider it (because this can happen). - Code cleanup such as moving class `static` members to the top, initialize numeric members and so on. - Use `producerSpeaker` to name values in `this->mapProducerSpeakers` instead of naming them `rtpObserver`. --- CHANGELOG.md | 1 + worker/include/RTC/ActiveSpeakerObserver.hpp | 36 ++-- worker/src/RTC/ActiveSpeakerObserver.cpp | 172 +++++++++++-------- 3 files changed, 117 insertions(+), 92 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index d8291194e2..6d3e45e97e 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -6,6 +6,7 @@ * Transport: Remove duplicate call to method (PR #931). * RTCP: Adjust maximum compound packet size (PR #934). * Fix `bufferedAmount` type to be a number again (PR #936). +* `ActiveSpeakerObserver`: Fix memory leak (PR #). ### 3.10.12 diff --git a/worker/include/RTC/ActiveSpeakerObserver.hpp b/worker/include/RTC/ActiveSpeakerObserver.hpp index af82153cca..da02d0033e 100644 --- a/worker/include/RTC/ActiveSpeakerObserver.hpp +++ b/worker/include/RTC/ActiveSpeakerObserver.hpp @@ -9,10 +9,9 @@ #include // Implementation of Dominant Speaker Identification for Multipoint -// Videoconferencing by Ilana Volfin and Israel Cohen. This -// implementation uses the RTP Audio Level extension from RFC-6464 -// for the input signal. -// This has been ported from DominantSpeakerIdentification.java in Jitsi. +// Videoconferencing by Ilana Volfin and Israel Cohen. This implementation uses +// the RTP Audio Level extension from RFC-6464 for the input signal. This has +// been ported from DominantSpeakerIdentification.java in Jitsi: // https://github.com/jitsi/jitsi-utils/blob/master/src/main/java/org/jitsi/utils/dsi/DominantSpeakerIdentification.java namespace RTC { @@ -24,7 +23,7 @@ namespace RTC public: Speaker(); void EvalActivityScores(); - double GetActivityScore(int32_t interval); + double GetActivityScore(uint8_t interval); void LevelChanged(uint32_t level, uint64_t now); void LevelTimedOut(uint64_t now); @@ -39,20 +38,20 @@ namespace RTC public: bool paused{ false }; - double immediateActivityScore; - double mediumActivityScore; - double longActivityScore; + double immediateActivityScore{ 0 }; + double mediumActivityScore{ 0 }; + double longActivityScore{ 0 }; uint64_t lastLevelChangeTime{ 0 }; private: - uint8_t minLevel; - uint8_t nextMinLevel; - uint32_t nextMinLevelWindowLen{ 0 }; + uint8_t minLevel{ 0u }; + uint8_t nextMinLevel{ 0u }; + uint32_t nextMinLevelWindowLen{ 0u }; std::vector immediates; std::vector mediums; std::vector longs; std::vector levels; - size_t nextLevelIndex; + size_t nextLevelIndex{ 0u }; }; struct ProducerSpeaker @@ -61,6 +60,9 @@ namespace RTC Speaker* speaker; }; + private: + static const size_t RelativeSpeachActivitiesLen{ 3u }; + public: ActiveSpeakerObserver(const std::string& id, RTC::RtpObserver::Listener* listener, json& data); ~ActiveSpeakerObserver() override; @@ -84,13 +86,13 @@ namespace RTC void OnTimer(Timer* timer) override; private: - static constexpr int relativeSpeachActivitiesLen{ 3 }; - double relativeSpeachActivities[relativeSpeachActivitiesLen]; - std::string dominantId{ "" }; + double relativeSpeachActivities[RelativeSpeachActivitiesLen]; + std::string dominantId; Timer* periodicTimer{ nullptr }; uint16_t interval{ 300u }; - absl::flat_hash_map mapProducerSpeaker; - uint64_t lastLevelIdleTime{ 0 }; + // Map of ProducerSpeakers indeed by Producer id. + absl::flat_hash_map mapProducerSpeakers; + uint64_t lastLevelIdleTime{ 0u }; }; } // namespace RTC diff --git a/worker/src/RTC/ActiveSpeakerObserver.cpp b/worker/src/RTC/ActiveSpeakerObserver.cpp index 2ab9f35240..cb59ba050c 100644 --- a/worker/src/RTC/ActiveSpeakerObserver.cpp +++ b/worker/src/RTC/ActiveSpeakerObserver.cpp @@ -10,26 +10,28 @@ namespace RTC { - constexpr uint32_t C1{ 3 }; - constexpr uint32_t C2{ 2 }; - constexpr uint32_t C3{ 0 }; - constexpr uint32_t N1{ 13 }; - constexpr uint32_t N2{ 5 }; - constexpr uint32_t N3{ 10 }; - constexpr uint32_t LongCount{ 1 }; - constexpr uint32_t LevelIdleTimeout{ 40 }; - constexpr uint64_t SpeakerIdleTimeout{ 60 * 60 * 1000 }; - constexpr uint32_t LongThreashold{ 4 }; - constexpr uint32_t MaxLevel{ 127 }; - constexpr uint32_t MinLevel{ 0 }; - constexpr uint32_t MinLevelWindowLen{ 15 * 1000 / 20 }; - constexpr uint32_t MediumThreshold{ 7 }; - constexpr uint32_t SubunitLengthN1{ (MaxLevel - MinLevel + N1 - 1) / N1 }; - constexpr uint32_t ImmediateBuffLen{ LongCount * N3 * N2 }; - constexpr uint32_t MediumsBuffLen{ LongCount * N3 }; - constexpr uint32_t LongsBuffLen{ LongCount }; - constexpr uint32_t LevelsBuffLen{ LongCount * N3 * N2 }; - constexpr double MinActivityScore{ 0.0000000001 }; + /* Static. */ + + static constexpr uint32_t C1{ 3u }; + static constexpr uint32_t C2{ 2u }; + static constexpr uint32_t C3{ 0u }; + static constexpr uint32_t N1{ 13u }; + static constexpr uint32_t N2{ 5u }; + static constexpr uint32_t N3{ 10u }; + static constexpr uint32_t LongCount{ 1u }; + static constexpr uint32_t LevelIdleTimeout{ 40u }; + static constexpr uint64_t SpeakerIdleTimeout{ 60 * 60 * 1000 }; + static constexpr uint32_t LongThreashold{ 4u }; + static constexpr uint32_t MaxLevel{ 127u }; + static constexpr uint32_t MinLevel{ 0u }; + static constexpr uint32_t MinLevelWindowLen{ 15 * 1000 / 20 }; + static constexpr uint32_t MediumThreshold{ 7u }; + static constexpr uint32_t SubunitLengthN1{ (MaxLevel - MinLevel + N1 - 1) / N1 }; + static constexpr uint32_t ImmediateBuffLen{ LongCount * N3 * N2 }; + static constexpr uint32_t MediumsBuffLen{ LongCount * N3 }; + static constexpr uint32_t LongsBuffLen{ LongCount }; + static constexpr uint32_t LevelsBuffLen{ LongCount * N3 * N2 }; + static constexpr double MinActivityScore{ 0.0000000001 }; inline int64_t BinomialCoefficient(int32_t n, int32_t r) { @@ -40,7 +42,8 @@ namespace RTC r = m; } - int64_t t = 1; + int64_t t{ 1 }; + for (int64_t i = n, j = 1; i > r; i--, ++j) { t = t * i / j; @@ -69,11 +72,11 @@ namespace RTC uint32_t littleLen = littles.size(); uint32_t bigLen = bigs.size(); uint32_t littleLenPerBig = littleLen / bigLen; - bool changed = false; + bool changed{ false }; - for (uint32_t b = 0, l = 0; b < bigLen; b++) + for (uint32_t b = 0u, l = 0u; b < bigLen; ++b) { - uint8_t sum = 0; + uint8_t sum{ 0u }; for (uint32_t lEnd = l + littleLenPerBig; l < lEnd; ++l) { @@ -132,6 +135,16 @@ namespace RTC ChannelMessageHandlers::UnregisterHandler(this->id); delete this->periodicTimer; + + // Must clear all entries in this->mapProducerSpeakers since RemoveProducer() + // won't be called for each existing Producer if the ActiveSpeakerObserver or + // its parent Router are directly closed. + for (auto& kv : this->mapProducerSpeakers) + { + auto& producerSpeaker = kv.second; + delete producerSpeaker.speaker; + } + this->mapProducerSpeakers.clear(); } void ActiveSpeakerObserver::AddProducer(RTC::Producer* producer) @@ -141,35 +154,38 @@ namespace RTC if (producer->GetKind() != RTC::Media::Kind::AUDIO) MS_THROW_TYPE_ERROR("not an audio Producer"); - if (this->mapProducerSpeaker.find(producer->id) != this->mapProducerSpeaker.end()) + if (this->mapProducerSpeakers.find(producer->id) != this->mapProducerSpeakers.end()) MS_THROW_ERROR("Producer already in map"); - this->mapProducerSpeaker[producer->id].producer = producer; - this->mapProducerSpeaker[producer->id].speaker = new Speaker(); + auto& producerSpeaker = this->mapProducerSpeakers[producer->id]; + + producerSpeaker.producer = producer; + producerSpeaker.speaker = new Speaker(); + producerSpeaker.speaker->paused = producer->IsPaused(); } void ActiveSpeakerObserver::RemoveProducer(RTC::Producer* producer) { MS_TRACE(); - auto it = this->mapProducerSpeaker.find(producer->id); + auto it = this->mapProducerSpeakers.find(producer->id); - if (it == this->mapProducerSpeaker.end()) + if (it == this->mapProducerSpeakers.end()) { return; } - if (it->second.speaker != nullptr) - { - delete it->second.speaker; - it->second.speaker = nullptr; - } + auto& producerSpeaker = it->second; + + delete producerSpeaker.speaker; + producerSpeaker.speaker = nullptr; - this->mapProducerSpeaker.erase(producer->id); + this->mapProducerSpeakers.erase(producer->id); if (producer->id == this->dominantId) { this->dominantId.erase(); + Update(); } } @@ -178,13 +194,13 @@ namespace RTC { MS_TRACE(); - auto it = this->mapProducerSpeaker.find(producer->id); + auto it = this->mapProducerSpeakers.find(producer->id); - if (it != this->mapProducerSpeaker.end()) + if (it != this->mapProducerSpeakers.end()) { - auto& rtpObserver = it->second; + auto& producerSpeaker = it->second; - rtpObserver.speaker->paused = false; + producerSpeaker.speaker->paused = false; } } @@ -192,13 +208,13 @@ namespace RTC { MS_TRACE(); - auto it = this->mapProducerSpeaker.find(producer->id); + auto it = this->mapProducerSpeakers.find(producer->id); - if (it != this->mapProducerSpeaker.end()) + if (it != this->mapProducerSpeakers.end()) { - auto& rtpObserver = it->second; + auto& producerSpeaker = it->second; - rtpObserver.speaker->paused = true; + producerSpeaker.speaker->paused = true; } } @@ -216,14 +232,14 @@ namespace RTC return; uint8_t volume = 127 - level; - auto it = this->mapProducerSpeaker.find(producer->id); + auto it = this->mapProducerSpeakers.find(producer->id); - if (it != this->mapProducerSpeaker.end()) + if (it != this->mapProducerSpeakers.end()) { - auto& rtpObserver = it->second; - uint64_t now = DepLibUV::GetTimeMs(); + auto& producerSpeaker = it->second; + uint64_t now = DepLibUV::GetTimeMs(); - rtpObserver.speaker->LevelChanged(volume, now); + producerSpeaker.speaker->LevelChanged(volume, now); } } @@ -260,10 +276,11 @@ namespace RTC { TimeoutIdleLevels(now); } + this->lastLevelIdleTime = now; } - if (!this->mapProducerSpeaker.empty() && CalculateActiveSpeaker()) + if (!this->mapProducerSpeakers.empty() && CalculateActiveSpeaker()) { json data = json::object(); data["producerId"] = this->dominantId; @@ -277,7 +294,7 @@ namespace RTC MS_TRACE(); std::string newDominantId; - int32_t speakerCount = this->mapProducerSpeaker.size(); + int32_t speakerCount = this->mapProducerSpeakers.size(); if (speakerCount == 0) { @@ -285,20 +302,20 @@ namespace RTC } else if (speakerCount == 1) { - auto it = this->mapProducerSpeaker.begin(); - - newDominantId = it->second.producer->id; + auto it = this->mapProducerSpeakers.begin(); + auto& producerSpeaker = it->second; + newDominantId = producerSpeaker.producer->id; } else { Speaker* dominantSpeaker = - (this->dominantId.empty()) ? nullptr : this->mapProducerSpeaker[this->dominantId].speaker; + (this->dominantId.empty()) ? nullptr : this->mapProducerSpeakers[this->dominantId].speaker; if (dominantSpeaker == nullptr) { - auto item = this->mapProducerSpeaker.begin(); - newDominantId = item->first; - dominantSpeaker = item->second.speaker; + auto it = this->mapProducerSpeakers.begin(); + newDominantId = it->first; + dominantSpeaker = it->second.speaker; } else { @@ -308,10 +325,11 @@ namespace RTC dominantSpeaker->EvalActivityScores(); double newDominantC2 = C2; - for (const auto& it : this->mapProducerSpeaker) + for (auto& kv : this->mapProducerSpeakers) { - Speaker* speaker = it.second.speaker; - const std::string& id = it.second.producer->id; + auto& producerSpeaker = kv.second; + auto* speaker = producerSpeaker.speaker; + auto& id = producerSpeaker.producer->id; if (id == this->dominantId || speaker->paused) { @@ -320,7 +338,8 @@ namespace RTC speaker->EvalActivityScores(); - for (int interval = 0; interval < this->relativeSpeachActivitiesLen; ++interval) + for (uint8_t interval = 0u; interval < ActiveSpeakerObserver::RelativeSpeachActivitiesLen; + ++interval) { this->relativeSpeachActivities[interval] = std::log( speaker->GetActivityScore(interval) / dominantSpeaker->GetActivityScore(interval)); @@ -329,6 +348,7 @@ namespace RTC double c1 = this->relativeSpeachActivities[0]; double c2 = this->relativeSpeachActivities[1]; double c3 = this->relativeSpeachActivities[2]; + if ((c1 > C1) && (c2 > C2) && (c3 > C3) && (c2 > newDominantC2)) { newDominantC2 = c2; @@ -351,10 +371,11 @@ namespace RTC { MS_TRACE(); - for (const auto& it : this->mapProducerSpeaker) + for (auto& kv : this->mapProducerSpeakers) { - Speaker* speaker = it.second.speaker; - const std::string& id = it.second.producer->id; + auto& producerSpeaker = kv.second; + auto* speaker = producerSpeaker.speaker; + auto& id = producerSpeaker.producer->id; uint64_t idle = now - speaker->lastLevelChangeTime; if (SpeakerIdleTimeout < idle && (this->dominantId.empty() || id != this->dominantId)) @@ -397,17 +418,17 @@ namespace RTC } } - double ActiveSpeakerObserver::Speaker::GetActivityScore(int32_t interval) + double ActiveSpeakerObserver::Speaker::GetActivityScore(uint8_t interval) { MS_TRACE(); switch (interval) { - case 0: + case 0u: return this->immediateActivityScore; - case 1: + case 1u: return this->mediumActivityScore; - case 2: + case 2u: return this->longActivityScore; default: MS_ABORT("interval is invalid"); @@ -424,7 +445,7 @@ namespace RTC this->lastLevelChangeTime = now; - int8_t b = 0; + int8_t b{ 0 }; if (level < MinLevel) { @@ -439,12 +460,13 @@ namespace RTC b = level; } - // The algorithm expect to have an update every 20 milliseconds. If the producer is paused, - // using a different packetization time or using DTX we need to update more than one sample - // when receiving an audio packet. + // The algorithm expect to have an update every 20 milliseconds. If the + // Producer is paused, using a different packetization time or using DTX + // we need to update more than one sample when receiving an audio packet. uint32_t intervalsUpdated = std::min(std::max(static_cast(elapsed / 20), 1U), LevelsBuffLen); - for (uint32_t i = 0; i < intervalsUpdated; i++) + + for (uint32_t i = 0; i < intervalsUpdated; ++i) { this->levels[this->nextLevelIndex] = b; this->nextLevelIndex = (this->nextLevelIndex + 1) % LevelsBuffLen; @@ -558,6 +580,7 @@ namespace RTC { this->nextMinLevel = level; } + this->nextMinLevelWindowLen++; if (this->nextMinLevelWindowLen >= MinLevelWindowLen) @@ -573,8 +596,7 @@ namespace RTC newMinLevel = MaxLevel; } - this->minLevel = static_cast(newMinLevel); - + this->minLevel = static_cast(newMinLevel); this->nextMinLevel = MinLevel; this->nextMinLevelWindowLen = 0; } From 5de84eaabc1d7af9ba2f175f838818215fcc3b2f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?I=C3=B1aki=20Baz=20Castillo?= Date: Fri, 4 Nov 2022 10:35:37 +0100 Subject: [PATCH 2/6] cosmetic --- CHANGELOG.md | 2 +- worker/src/RTC/ActiveSpeakerObserver.cpp | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 6d3e45e97e..5348a8bab1 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -6,7 +6,7 @@ * Transport: Remove duplicate call to method (PR #931). * RTCP: Adjust maximum compound packet size (PR #934). * Fix `bufferedAmount` type to be a number again (PR #936). -* `ActiveSpeakerObserver`: Fix memory leak (PR #). +* `ActiveSpeakerObserver`: Fix memory leak (PR #942). ### 3.10.12 diff --git a/worker/src/RTC/ActiveSpeakerObserver.cpp b/worker/src/RTC/ActiveSpeakerObserver.cpp index cb59ba050c..a63dcf0868 100644 --- a/worker/src/RTC/ActiveSpeakerObserver.cpp +++ b/worker/src/RTC/ActiveSpeakerObserver.cpp @@ -466,7 +466,7 @@ namespace RTC uint32_t intervalsUpdated = std::min(std::max(static_cast(elapsed / 20), 1U), LevelsBuffLen); - for (uint32_t i = 0; i < intervalsUpdated; ++i) + for (uint32_t i{ 0u }; i < intervalsUpdated; ++i) { this->levels[this->nextLevelIndex] = b; this->nextLevelIndex = (this->nextLevelIndex + 1) % LevelsBuffLen; From 1f78b93b283add286e2fe007b3c734d74819f3f0 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?I=C3=B1aki=20Baz=20Castillo?= Date: Fri, 4 Nov 2022 10:42:45 +0100 Subject: [PATCH 3/6] Update worker/include/RTC/ActiveSpeakerObserver.hpp MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Co-authored-by: José Luis Millán --- worker/include/RTC/ActiveSpeakerObserver.hpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/worker/include/RTC/ActiveSpeakerObserver.hpp b/worker/include/RTC/ActiveSpeakerObserver.hpp index da02d0033e..da4ac9e682 100644 --- a/worker/include/RTC/ActiveSpeakerObserver.hpp +++ b/worker/include/RTC/ActiveSpeakerObserver.hpp @@ -90,7 +90,7 @@ namespace RTC std::string dominantId; Timer* periodicTimer{ nullptr }; uint16_t interval{ 300u }; - // Map of ProducerSpeakers indeed by Producer id. + // Map of ProducerSpeakers indexed by Producer id. absl::flat_hash_map mapProducerSpeakers; uint64_t lastLevelIdleTime{ 0u }; }; From 7d19a2522a9b5c2c85c440a79199220dd97dca6f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?I=C3=B1aki=20Baz=20Castillo?= Date: Fri, 4 Nov 2022 11:29:32 +0100 Subject: [PATCH 4/6] foo --- worker/include/RTC/ActiveSpeakerObserver.hpp | 11 ++- worker/src/RTC/ActiveSpeakerObserver.cpp | 75 ++++++++++++-------- 2 files changed, 52 insertions(+), 34 deletions(-) diff --git a/worker/include/RTC/ActiveSpeakerObserver.hpp b/worker/include/RTC/ActiveSpeakerObserver.hpp index da4ac9e682..84609557b8 100644 --- a/worker/include/RTC/ActiveSpeakerObserver.hpp +++ b/worker/include/RTC/ActiveSpeakerObserver.hpp @@ -54,8 +54,13 @@ namespace RTC size_t nextLevelIndex{ 0u }; }; - struct ProducerSpeaker + class ProducerSpeaker { + public: + ProducerSpeaker(RTC::Producer* producer); + ~ProducerSpeaker(); + + public: RTC::Producer* producer; Speaker* speaker; }; @@ -90,8 +95,8 @@ namespace RTC std::string dominantId; Timer* periodicTimer{ nullptr }; uint16_t interval{ 300u }; - // Map of ProducerSpeakers indexed by Producer id. - absl::flat_hash_map mapProducerSpeakers; + // Map of ProducerSpeakers indeed by Producer id. + absl::flat_hash_map mapProducerSpeakers; uint64_t lastLevelIdleTime{ 0u }; }; } // namespace RTC diff --git a/worker/src/RTC/ActiveSpeakerObserver.cpp b/worker/src/RTC/ActiveSpeakerObserver.cpp index a63dcf0868..9040b28cd6 100644 --- a/worker/src/RTC/ActiveSpeakerObserver.cpp +++ b/worker/src/RTC/ActiveSpeakerObserver.cpp @@ -141,8 +141,8 @@ namespace RTC // its parent Router are directly closed. for (auto& kv : this->mapProducerSpeakers) { - auto& producerSpeaker = kv.second; - delete producerSpeaker.speaker; + auto* producerSpeaker = kv.second; + delete producerSpeaker; } this->mapProducerSpeakers.clear(); } @@ -157,11 +157,7 @@ namespace RTC if (this->mapProducerSpeakers.find(producer->id) != this->mapProducerSpeakers.end()) MS_THROW_ERROR("Producer already in map"); - auto& producerSpeaker = this->mapProducerSpeakers[producer->id]; - - producerSpeaker.producer = producer; - producerSpeaker.speaker = new Speaker(); - producerSpeaker.speaker->paused = producer->IsPaused(); + this->mapProducerSpeakers[producer->id] = new ProducerSpeaker(producer); } void ActiveSpeakerObserver::RemoveProducer(RTC::Producer* producer) @@ -175,10 +171,9 @@ namespace RTC return; } - auto& producerSpeaker = it->second; + auto* producerSpeaker = it->second; - delete producerSpeaker.speaker; - producerSpeaker.speaker = nullptr; + delete producerSpeaker; this->mapProducerSpeakers.erase(producer->id); @@ -190,7 +185,7 @@ namespace RTC } } - void ActiveSpeakerObserver::ProducerResumed(RTC::Producer* producer) + void ActiveSpeakerObserver::ProducerPaused(RTC::Producer* producer) { MS_TRACE(); @@ -198,13 +193,13 @@ namespace RTC if (it != this->mapProducerSpeakers.end()) { - auto& producerSpeaker = it->second; + auto* producerSpeaker = it->second; - producerSpeaker.speaker->paused = false; + producerSpeaker->speaker->paused = true; } } - void ActiveSpeakerObserver::ProducerPaused(RTC::Producer* producer) + void ActiveSpeakerObserver::ProducerResumed(RTC::Producer* producer) { MS_TRACE(); @@ -212,9 +207,9 @@ namespace RTC if (it != this->mapProducerSpeakers.end()) { - auto& producerSpeaker = it->second; + auto* producerSpeaker = it->second; - producerSpeaker.speaker->paused = true; + producerSpeaker->speaker->paused = false; } } @@ -236,10 +231,10 @@ namespace RTC if (it != this->mapProducerSpeakers.end()) { - auto& producerSpeaker = it->second; + auto* producerSpeaker = it->second; uint64_t now = DepLibUV::GetTimeMs(); - producerSpeaker.speaker->LevelChanged(volume, now); + producerSpeaker->speaker->LevelChanged(volume, now); } } @@ -303,19 +298,21 @@ namespace RTC else if (speakerCount == 1) { auto it = this->mapProducerSpeakers.begin(); - auto& producerSpeaker = it->second; - newDominantId = producerSpeaker.producer->id; + auto* producerSpeaker = it->second; + newDominantId = producerSpeaker->producer->id; } else { - Speaker* dominantSpeaker = - (this->dominantId.empty()) ? nullptr : this->mapProducerSpeakers[this->dominantId].speaker; + Speaker* dominantSpeaker = (this->dominantId.empty()) + ? nullptr + : this->mapProducerSpeakers.at(this->dominantId)->speaker; if (dominantSpeaker == nullptr) { - auto it = this->mapProducerSpeakers.begin(); - newDominantId = it->first; - dominantSpeaker = it->second.speaker; + auto it = this->mapProducerSpeakers.begin(); + newDominantId = it->first; + auto* producerSpeaker = it->second; + dominantSpeaker = producerSpeaker->speaker; } else { @@ -327,9 +324,9 @@ namespace RTC for (auto& kv : this->mapProducerSpeakers) { - auto& producerSpeaker = kv.second; - auto* speaker = producerSpeaker.speaker; - auto& id = producerSpeaker.producer->id; + auto* producerSpeaker = kv.second; + auto* speaker = producerSpeaker->speaker; + auto& id = producerSpeaker->producer->id; if (id == this->dominantId || speaker->paused) { @@ -373,9 +370,9 @@ namespace RTC for (auto& kv : this->mapProducerSpeakers) { - auto& producerSpeaker = kv.second; - auto* speaker = producerSpeaker.speaker; - auto& id = producerSpeaker.producer->id; + auto* producerSpeaker = kv.second; + auto* speaker = producerSpeaker->speaker; + auto& id = producerSpeaker->producer->id; uint64_t idle = now - speaker->lastLevelChangeTime; if (SpeakerIdleTimeout < idle && (this->dominantId.empty() || id != this->dominantId)) @@ -389,6 +386,22 @@ namespace RTC } } + ActiveSpeakerObserver::ProducerSpeaker::ProducerSpeaker(RTC::Producer* producer) + : producer(producer) + { + MS_TRACE(); + + this->speaker = new Speaker(); + this->speaker->paused = producer->IsPaused(); + } + + ActiveSpeakerObserver::ProducerSpeaker::~ProducerSpeaker() + { + MS_TRACE(); + + delete this->speaker; + } + ActiveSpeakerObserver::Speaker::Speaker() : immediateActivityScore(MinActivityScore), mediumActivityScore(MinActivityScore), longActivityScore(MinActivityScore), lastLevelChangeTime(DepLibUV::GetTimeMs()), From 48c94c908e4047d921c6411b2dd34f203052ec16 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?I=C3=B1aki=20Baz=20Castillo?= Date: Fri, 4 Nov 2022 11:31:16 +0100 Subject: [PATCH 5/6] fix typo --- worker/include/RTC/ActiveSpeakerObserver.hpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/worker/include/RTC/ActiveSpeakerObserver.hpp b/worker/include/RTC/ActiveSpeakerObserver.hpp index 84609557b8..76e2f50221 100644 --- a/worker/include/RTC/ActiveSpeakerObserver.hpp +++ b/worker/include/RTC/ActiveSpeakerObserver.hpp @@ -95,7 +95,7 @@ namespace RTC std::string dominantId; Timer* periodicTimer{ nullptr }; uint16_t interval{ 300u }; - // Map of ProducerSpeakers indeed by Producer id. + // Map of ProducerSpeakers indexed by Producer id. absl::flat_hash_map mapProducerSpeakers; uint64_t lastLevelIdleTime{ 0u }; }; From 3097cbe25a900377c32984d75bcc6241552aedf5 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?I=C3=B1aki=20Baz=20Castillo?= Date: Fri, 4 Nov 2022 11:34:15 +0100 Subject: [PATCH 6/6] Use explicit --- worker/include/RTC/ActiveSpeakerObserver.hpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/worker/include/RTC/ActiveSpeakerObserver.hpp b/worker/include/RTC/ActiveSpeakerObserver.hpp index 76e2f50221..d5160fe7f1 100644 --- a/worker/include/RTC/ActiveSpeakerObserver.hpp +++ b/worker/include/RTC/ActiveSpeakerObserver.hpp @@ -57,7 +57,7 @@ namespace RTC class ProducerSpeaker { public: - ProducerSpeaker(RTC::Producer* producer); + explicit ProducerSpeaker(RTC::Producer* producer); ~ProducerSpeaker(); public: