Add audio level to CSRC class

This patch adds (optional) csrc to ContributingSources.
This will be used if using virtual audio ssrc, since
the audio level is otherwise unaccessible in that configuration.

BUG=webrtc:3333

Change-Id: Ied263b8f0850553cd637fd6bead373ed4252fd1e
Reviewed-on: https://webrtc-review.googlesource.com/c/109281
Reviewed-by: Oskar Sundbom <ossu@webrtc.org>
Reviewed-by: Åsa Persson <asapersson@webrtc.org>
Reviewed-by: Niels Moller <nisse@webrtc.org>
Reviewed-by: Danil Chapovalov <danilchap@webrtc.org>
Commit-Queue: Jonas Oreland <jonaso@webrtc.org>
Cr-Commit-Position: refs/heads/master@{#25516}
This commit is contained in:
Jonas Oreland
2018-11-06 07:35:06 +01:00
committed by Commit Bot
parent df351f4b54
commit 967f7d5497
5 changed files with 64 additions and 22 deletions

View File

@ -437,7 +437,9 @@ void ChannelReceive::OnRtpPacket(const RtpPacketReceived& packet) {
if (has_audio_level) if (has_audio_level)
last_received_rtp_audio_level_ = audio_level; last_received_rtp_audio_level_ = audio_level;
std::vector<uint32_t> csrcs = packet.Csrcs(); std::vector<uint32_t> csrcs = packet.Csrcs();
contributing_sources_.Update(now_ms, csrcs); contributing_sources_.Update(
now_ms, csrcs,
has_audio_level ? absl::optional<uint8_t>(audio_level) : absl::nullopt);
} }
// Store playout timestamp for the received RTP packet // Store playout timestamp for the received RTP packet

View File

@ -25,9 +25,11 @@ ContributingSources::ContributingSources() = default;
ContributingSources::~ContributingSources() = default; ContributingSources::~ContributingSources() = default;
void ContributingSources::Update(int64_t now_ms, void ContributingSources::Update(int64_t now_ms,
rtc::ArrayView<const uint32_t> csrcs) { rtc::ArrayView<const uint32_t> csrcs,
absl::optional<uint8_t> audio_level) {
Entry entry = { now_ms, audio_level };
for (uint32_t csrc : csrcs) { for (uint32_t csrc : csrcs) {
last_seen_ms_[csrc] = now_ms; active_csrcs_[csrc] = entry;
} }
if (!next_pruning_ms_) { if (!next_pruning_ms_) {
next_pruning_ms_ = now_ms + kPruningIntervalMs; next_pruning_ms_ = now_ms + kPruningIntervalMs;
@ -43,9 +45,16 @@ void ContributingSources::Update(int64_t now_ms,
// non-const. // non-const.
std::vector<RtpSource> ContributingSources::GetSources(int64_t now_ms) const { std::vector<RtpSource> ContributingSources::GetSources(int64_t now_ms) const {
std::vector<RtpSource> sources; std::vector<RtpSource> sources;
for (auto& record : last_seen_ms_) { for (auto& record : active_csrcs_) {
if (record.second >= now_ms - kHistoryMs) { if (record.second.last_seen_ms >= now_ms - kHistoryMs) {
sources.emplace_back(record.second, record.first, RtpSourceType::CSRC); 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<RtpSource> ContributingSources::GetSources(int64_t now_ms) const {
// Delete stale entries. // Delete stale entries.
void ContributingSources::DeleteOldEntries(int64_t now_ms) { void ContributingSources::DeleteOldEntries(int64_t now_ms) {
for (auto it = last_seen_ms_.begin(); it != last_seen_ms_.end();) { for (auto it = active_csrcs_.begin(); it != active_csrcs_.end();) {
if (it->second >= now_ms - kHistoryMs) { if (it->second.last_seen_ms >= now_ms - kHistoryMs) {
// Still relevant. // Still relevant.
++it; ++it;
} else { } else {
it = last_seen_ms_.erase(it); it = active_csrcs_.erase(it);
} }
} }
next_pruning_ms_ = now_ms + kPruningIntervalMs; next_pruning_ms_ = now_ms + kPruningIntervalMs;
} }
ContributingSources::Entry::Entry() = default;
ContributingSources::Entry::Entry(int64_t timestamp_ms,
absl::optional<uint8_t> audio_level_arg)
: last_seen_ms(timestamp_ms), audio_level(audio_level_arg) {}
} // namespace webrtc } // namespace webrtc

View File

@ -32,18 +32,25 @@ class ContributingSources {
ContributingSources(); ContributingSources();
~ContributingSources(); ~ContributingSources();
// TODO(bugs.webrtc.org/3333): Needs to be extended with audio-level, to void Update(int64_t now_ms, rtc::ArrayView<const uint32_t> csrcs,
// support RFC6465. absl::optional<uint8_t> audio_level);
void Update(int64_t now_ms, rtc::ArrayView<const uint32_t> csrcs);
// Returns contributing sources seen the last 10 s. // Returns contributing sources seen the last 10 s.
std::vector<RtpSource> GetSources(int64_t now_ms) const; std::vector<RtpSource> GetSources(int64_t now_ms) const;
private: private:
struct Entry {
Entry();
Entry(int64_t timestamp_ms, absl::optional<uint8_t> audio_level);
int64_t last_seen_ms;
absl::optional<uint8_t> audio_level;
};
void DeleteOldEntries(int64_t now_ms); void DeleteOldEntries(int64_t now_ms);
// Indexed by csrc. // Indexed by csrc.
std::map<uint32_t, int64_t> last_seen_ms_; std::map<uint32_t, Entry> active_csrcs_;
absl::optional<int64_t> next_pruning_ms_; absl::optional<int64_t> next_pruning_ms_;
}; };

View File

@ -30,7 +30,7 @@ TEST(ContributingSourcesTest, RecordSources) {
ContributingSources csrcs; ContributingSources csrcs;
constexpr uint32_t kCsrcs[] = {kCsrc1, kCsrc2}; constexpr uint32_t kCsrcs[] = {kCsrc1, kCsrc2};
constexpr int64_t kTime1 = 10; constexpr int64_t kTime1 = 10;
csrcs.Update(kTime1, kCsrcs); csrcs.Update(kTime1, kCsrcs, absl::nullopt);
EXPECT_THAT( EXPECT_THAT(
csrcs.GetSources(kTime1), csrcs.GetSources(kTime1),
UnorderedElementsAre(RtpSource(kTime1, kCsrc1, RtpSourceType::CSRC), UnorderedElementsAre(RtpSource(kTime1, kCsrc1, RtpSourceType::CSRC),
@ -45,12 +45,12 @@ TEST(ContributingSourcesTest, UpdateSources) {
constexpr uint32_t kCsrcs2[] = {kCsrc2, kCsrc3}; constexpr uint32_t kCsrcs2[] = {kCsrc2, kCsrc3};
constexpr int64_t kTime1 = 10; constexpr int64_t kTime1 = 10;
constexpr int64_t kTime2 = kTime1 + 5 * rtc::kNumMillisecsPerSec; constexpr int64_t kTime2 = kTime1 + 5 * rtc::kNumMillisecsPerSec;
csrcs.Update(kTime1, kCsrcs1); csrcs.Update(kTime1, kCsrcs1, absl::nullopt);
EXPECT_THAT( EXPECT_THAT(
csrcs.GetSources(kTime1), csrcs.GetSources(kTime1),
UnorderedElementsAre(RtpSource(kTime1, kCsrc1, RtpSourceType::CSRC), UnorderedElementsAre(RtpSource(kTime1, kCsrc1, RtpSourceType::CSRC),
RtpSource(kTime1, kCsrc2, RtpSourceType::CSRC))); RtpSource(kTime1, kCsrc2, RtpSourceType::CSRC)));
csrcs.Update(kTime2, kCsrcs2); csrcs.Update(kTime2, kCsrcs2, absl::nullopt);
EXPECT_THAT( EXPECT_THAT(
csrcs.GetSources(kTime2), csrcs.GetSources(kTime2),
UnorderedElementsAre(RtpSource(kTime1, kCsrc1, RtpSourceType::CSRC), UnorderedElementsAre(RtpSource(kTime1, kCsrc1, RtpSourceType::CSRC),
@ -65,12 +65,12 @@ TEST(ContributingSourcesTest, ReturnRecentOnly) {
constexpr int64_t kTime1 = 10; constexpr int64_t kTime1 = 10;
constexpr int64_t kTime2 = kTime1 + 5 * rtc::kNumMillisecsPerSec; constexpr int64_t kTime2 = kTime1 + 5 * rtc::kNumMillisecsPerSec;
constexpr int64_t kTime3 = kTime1 + 12 * rtc::kNumMillisecsPerSec; constexpr int64_t kTime3 = kTime1 + 12 * rtc::kNumMillisecsPerSec;
csrcs.Update(kTime1, kCsrcs1); csrcs.Update(kTime1, kCsrcs1, absl::nullopt);
EXPECT_THAT( EXPECT_THAT(
csrcs.GetSources(kTime1), csrcs.GetSources(kTime1),
UnorderedElementsAre(RtpSource(kTime1, kCsrc1, RtpSourceType::CSRC), UnorderedElementsAre(RtpSource(kTime1, kCsrc1, RtpSourceType::CSRC),
RtpSource(kTime1, kCsrc2, RtpSourceType::CSRC))); RtpSource(kTime1, kCsrc2, RtpSourceType::CSRC)));
csrcs.Update(kTime2, kCsrcs2); csrcs.Update(kTime2, kCsrcs2, absl::nullopt);
EXPECT_THAT( EXPECT_THAT(
csrcs.GetSources(kTime3), csrcs.GetSources(kTime3),
UnorderedElementsAre(RtpSource(kTime2, kCsrc2, RtpSourceType::CSRC), UnorderedElementsAre(RtpSource(kTime2, kCsrc2, RtpSourceType::CSRC),
@ -84,18 +84,18 @@ TEST(ContributingSourcesTest, PurgeOldSources) {
constexpr int64_t kTime1 = 10; constexpr int64_t kTime1 = 10;
constexpr int64_t kTime2 = kTime1 + 10 * rtc::kNumMillisecsPerSec; constexpr int64_t kTime2 = kTime1 + 10 * rtc::kNumMillisecsPerSec;
constexpr int64_t kTime3 = kTime1 + 20 * rtc::kNumMillisecsPerSec; constexpr int64_t kTime3 = kTime1 + 20 * rtc::kNumMillisecsPerSec;
csrcs.Update(kTime1, kCsrcs1); csrcs.Update(kTime1, kCsrcs1, absl::nullopt);
EXPECT_THAT( EXPECT_THAT(
csrcs.GetSources(kTime2), csrcs.GetSources(kTime2),
UnorderedElementsAre(RtpSource(kTime1, kCsrc1, RtpSourceType::CSRC), UnorderedElementsAre(RtpSource(kTime1, kCsrc1, RtpSourceType::CSRC),
RtpSource(kTime1, kCsrc2, RtpSourceType::CSRC))); RtpSource(kTime1, kCsrc2, RtpSourceType::CSRC)));
csrcs.Update(kTime2, kCsrcs2); csrcs.Update(kTime2, kCsrcs2, absl::nullopt);
EXPECT_THAT( EXPECT_THAT(
csrcs.GetSources(kTime2), csrcs.GetSources(kTime2),
UnorderedElementsAre(RtpSource(kTime1, kCsrc1, RtpSourceType::CSRC), UnorderedElementsAre(RtpSource(kTime1, kCsrc1, RtpSourceType::CSRC),
RtpSource(kTime2, kCsrc2, RtpSourceType::CSRC), RtpSource(kTime2, kCsrc2, RtpSourceType::CSRC),
RtpSource(kTime2, kCsrc3, RtpSourceType::CSRC))); RtpSource(kTime2, kCsrc3, RtpSourceType::CSRC)));
csrcs.Update(kTime3, kCsrcs2); csrcs.Update(kTime3, kCsrcs2, absl::nullopt);
EXPECT_THAT( EXPECT_THAT(
csrcs.GetSources(kTime3), csrcs.GetSources(kTime3),
UnorderedElementsAre(RtpSource(kTime3, kCsrc2, RtpSourceType::CSRC), UnorderedElementsAre(RtpSource(kTime3, kCsrc2, RtpSourceType::CSRC),
@ -108,4 +108,22 @@ TEST(ContributingSourcesTest, PurgeOldSources) {
RtpSource(kTime3, kCsrc3, RtpSourceType::CSRC))); 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 } // namespace webrtc

View File

@ -320,7 +320,8 @@ void RtpVideoStreamReceiver::OnRtpPacket(const RtpPacketReceived& packet) {
last_received_rtp_system_time_ms_ = now_ms; last_received_rtp_system_time_ms_ = now_ms;
std::vector<uint32_t> csrcs = packet.Csrcs(); std::vector<uint32_t> 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. // Periodically log the RTP header of incoming packets.
if (now_ms - last_packet_log_ms_ > kPacketLogIntervalMs) { if (now_ms - last_packet_log_ms_ > kPacketLogIntervalMs) {