diff --git a/audio/channel_receive.cc b/audio/channel_receive.cc index ac02482427..704ba7963e 100644 --- a/audio/channel_receive.cc +++ b/audio/channel_receive.cc @@ -437,7 +437,9 @@ void ChannelReceive::OnRtpPacket(const RtpPacketReceived& packet) { if (has_audio_level) last_received_rtp_audio_level_ = audio_level; std::vector csrcs = packet.Csrcs(); - contributing_sources_.Update(now_ms, csrcs); + contributing_sources_.Update( + now_ms, csrcs, + has_audio_level ? absl::optional(audio_level) : absl::nullopt); } // Store playout timestamp for the received RTP packet diff --git a/modules/rtp_rtcp/source/contributing_sources.cc b/modules/rtp_rtcp/source/contributing_sources.cc index 853706c4f5..64dc443e29 100644 --- a/modules/rtp_rtcp/source/contributing_sources.cc +++ b/modules/rtp_rtcp/source/contributing_sources.cc @@ -25,9 +25,11 @@ ContributingSources::ContributingSources() = default; ContributingSources::~ContributingSources() = default; void ContributingSources::Update(int64_t now_ms, - rtc::ArrayView csrcs) { + rtc::ArrayView csrcs, + absl::optional audio_level) { + Entry entry = { now_ms, audio_level }; for (uint32_t csrc : csrcs) { - last_seen_ms_[csrc] = now_ms; + active_csrcs_[csrc] = entry; } if (!next_pruning_ms_) { next_pruning_ms_ = now_ms + kPruningIntervalMs; @@ -43,9 +45,16 @@ void ContributingSources::Update(int64_t now_ms, // non-const. std::vector ContributingSources::GetSources(int64_t now_ms) const { std::vector sources; - for (auto& record : last_seen_ms_) { - if (record.second >= now_ms - kHistoryMs) { - sources.emplace_back(record.second, record.first, RtpSourceType::CSRC); + for (auto& record : active_csrcs_) { + if (record.second.last_seen_ms >= now_ms - kHistoryMs) { + if (record.second.audio_level.has_value()) { + sources.emplace_back(record.second.last_seen_ms, record.first, + RtpSourceType::CSRC, + *record.second.audio_level); + } else { + sources.emplace_back(record.second.last_seen_ms, record.first, + RtpSourceType::CSRC); + } } } @@ -54,15 +63,20 @@ std::vector ContributingSources::GetSources(int64_t now_ms) const { // Delete stale entries. void ContributingSources::DeleteOldEntries(int64_t now_ms) { - for (auto it = last_seen_ms_.begin(); it != last_seen_ms_.end();) { - if (it->second >= now_ms - kHistoryMs) { + for (auto it = active_csrcs_.begin(); it != active_csrcs_.end();) { + if (it->second.last_seen_ms >= now_ms - kHistoryMs) { // Still relevant. ++it; } else { - it = last_seen_ms_.erase(it); + it = active_csrcs_.erase(it); } } next_pruning_ms_ = now_ms + kPruningIntervalMs; } +ContributingSources::Entry::Entry() = default; +ContributingSources::Entry::Entry(int64_t timestamp_ms, + absl::optional audio_level_arg) + : last_seen_ms(timestamp_ms), audio_level(audio_level_arg) {} + } // namespace webrtc diff --git a/modules/rtp_rtcp/source/contributing_sources.h b/modules/rtp_rtcp/source/contributing_sources.h index b6201ce794..5e34539ce4 100644 --- a/modules/rtp_rtcp/source/contributing_sources.h +++ b/modules/rtp_rtcp/source/contributing_sources.h @@ -32,18 +32,25 @@ class ContributingSources { ContributingSources(); ~ContributingSources(); - // TODO(bugs.webrtc.org/3333): Needs to be extended with audio-level, to - // support RFC6465. - void Update(int64_t now_ms, rtc::ArrayView csrcs); + void Update(int64_t now_ms, rtc::ArrayView csrcs, + absl::optional audio_level); // Returns contributing sources seen the last 10 s. std::vector GetSources(int64_t now_ms) const; private: + struct Entry { + Entry(); + Entry(int64_t timestamp_ms, absl::optional audio_level); + + int64_t last_seen_ms; + absl::optional audio_level; + }; + void DeleteOldEntries(int64_t now_ms); // Indexed by csrc. - std::map last_seen_ms_; + std::map active_csrcs_; absl::optional next_pruning_ms_; }; diff --git a/modules/rtp_rtcp/source/contributing_sources_unittest.cc b/modules/rtp_rtcp/source/contributing_sources_unittest.cc index 8b22d26c94..5f1d8d3d11 100644 --- a/modules/rtp_rtcp/source/contributing_sources_unittest.cc +++ b/modules/rtp_rtcp/source/contributing_sources_unittest.cc @@ -30,7 +30,7 @@ TEST(ContributingSourcesTest, RecordSources) { ContributingSources csrcs; constexpr uint32_t kCsrcs[] = {kCsrc1, kCsrc2}; constexpr int64_t kTime1 = 10; - csrcs.Update(kTime1, kCsrcs); + csrcs.Update(kTime1, kCsrcs, absl::nullopt); EXPECT_THAT( csrcs.GetSources(kTime1), UnorderedElementsAre(RtpSource(kTime1, kCsrc1, RtpSourceType::CSRC), @@ -45,12 +45,12 @@ TEST(ContributingSourcesTest, UpdateSources) { constexpr uint32_t kCsrcs2[] = {kCsrc2, kCsrc3}; constexpr int64_t kTime1 = 10; constexpr int64_t kTime2 = kTime1 + 5 * rtc::kNumMillisecsPerSec; - csrcs.Update(kTime1, kCsrcs1); + csrcs.Update(kTime1, kCsrcs1, absl::nullopt); EXPECT_THAT( csrcs.GetSources(kTime1), UnorderedElementsAre(RtpSource(kTime1, kCsrc1, RtpSourceType::CSRC), RtpSource(kTime1, kCsrc2, RtpSourceType::CSRC))); - csrcs.Update(kTime2, kCsrcs2); + csrcs.Update(kTime2, kCsrcs2, absl::nullopt); EXPECT_THAT( csrcs.GetSources(kTime2), UnorderedElementsAre(RtpSource(kTime1, kCsrc1, RtpSourceType::CSRC), @@ -65,12 +65,12 @@ TEST(ContributingSourcesTest, ReturnRecentOnly) { constexpr int64_t kTime1 = 10; constexpr int64_t kTime2 = kTime1 + 5 * rtc::kNumMillisecsPerSec; constexpr int64_t kTime3 = kTime1 + 12 * rtc::kNumMillisecsPerSec; - csrcs.Update(kTime1, kCsrcs1); + csrcs.Update(kTime1, kCsrcs1, absl::nullopt); EXPECT_THAT( csrcs.GetSources(kTime1), UnorderedElementsAre(RtpSource(kTime1, kCsrc1, RtpSourceType::CSRC), RtpSource(kTime1, kCsrc2, RtpSourceType::CSRC))); - csrcs.Update(kTime2, kCsrcs2); + csrcs.Update(kTime2, kCsrcs2, absl::nullopt); EXPECT_THAT( csrcs.GetSources(kTime3), UnorderedElementsAre(RtpSource(kTime2, kCsrc2, RtpSourceType::CSRC), @@ -84,18 +84,18 @@ TEST(ContributingSourcesTest, PurgeOldSources) { constexpr int64_t kTime1 = 10; constexpr int64_t kTime2 = kTime1 + 10 * rtc::kNumMillisecsPerSec; constexpr int64_t kTime3 = kTime1 + 20 * rtc::kNumMillisecsPerSec; - csrcs.Update(kTime1, kCsrcs1); + csrcs.Update(kTime1, kCsrcs1, absl::nullopt); EXPECT_THAT( csrcs.GetSources(kTime2), UnorderedElementsAre(RtpSource(kTime1, kCsrc1, RtpSourceType::CSRC), RtpSource(kTime1, kCsrc2, RtpSourceType::CSRC))); - csrcs.Update(kTime2, kCsrcs2); + csrcs.Update(kTime2, kCsrcs2, absl::nullopt); EXPECT_THAT( csrcs.GetSources(kTime2), UnorderedElementsAre(RtpSource(kTime1, kCsrc1, RtpSourceType::CSRC), RtpSource(kTime2, kCsrc2, RtpSourceType::CSRC), RtpSource(kTime2, kCsrc3, RtpSourceType::CSRC))); - csrcs.Update(kTime3, kCsrcs2); + csrcs.Update(kTime3, kCsrcs2, absl::nullopt); EXPECT_THAT( csrcs.GetSources(kTime3), UnorderedElementsAre(RtpSource(kTime3, kCsrc2, RtpSourceType::CSRC), @@ -108,4 +108,22 @@ TEST(ContributingSourcesTest, PurgeOldSources) { RtpSource(kTime3, kCsrc3, RtpSourceType::CSRC))); } +TEST(ContributingSourcesTest, AudioLevel) { + ContributingSources csrcs; + constexpr uint32_t kCsrcs[] = {kCsrc1, kCsrc2}; + constexpr int64_t kTime1 = 10; + csrcs.Update(kTime1, kCsrcs, 47); + EXPECT_THAT( + csrcs.GetSources(kTime1), + UnorderedElementsAre(RtpSource(kTime1, kCsrc1, RtpSourceType::CSRC, 47), + RtpSource(kTime1, kCsrc2, RtpSourceType::CSRC, 47))); + + constexpr uint32_t kCsrcsSubset[] = {kCsrc1}; + csrcs.Update(kTime1 + 1, kCsrcsSubset, absl::nullopt); + EXPECT_THAT( + csrcs.GetSources(kTime1 + 1), + UnorderedElementsAre(RtpSource(kTime1 + 1, kCsrc1, RtpSourceType::CSRC), + RtpSource(kTime1, kCsrc2, RtpSourceType::CSRC, 47))); +} + } // namespace webrtc diff --git a/video/rtp_video_stream_receiver.cc b/video/rtp_video_stream_receiver.cc index 54956688ad..abf88d4371 100644 --- a/video/rtp_video_stream_receiver.cc +++ b/video/rtp_video_stream_receiver.cc @@ -320,7 +320,8 @@ void RtpVideoStreamReceiver::OnRtpPacket(const RtpPacketReceived& packet) { last_received_rtp_system_time_ms_ = now_ms; std::vector csrcs = packet.Csrcs(); - contributing_sources_.Update(now_ms, csrcs); + contributing_sources_.Update(now_ms, csrcs, + /* audio level */absl::nullopt); } // Periodically log the RTP header of incoming packets. if (now_ms - last_packet_log_ms_ > kPacketLogIntervalMs) {