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:

committed by
Commit Bot

parent
df351f4b54
commit
967f7d5497
@ -437,7 +437,9 @@ void ChannelReceive::OnRtpPacket(const RtpPacketReceived& packet) {
|
||||
if (has_audio_level)
|
||||
last_received_rtp_audio_level_ = audio_level;
|
||||
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
|
||||
|
@ -25,9 +25,11 @@ ContributingSources::ContributingSources() = default;
|
||||
ContributingSources::~ContributingSources() = default;
|
||||
|
||||
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) {
|
||||
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<RtpSource> ContributingSources::GetSources(int64_t now_ms) const {
|
||||
std::vector<RtpSource> 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<RtpSource> 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<uint8_t> audio_level_arg)
|
||||
: last_seen_ms(timestamp_ms), audio_level(audio_level_arg) {}
|
||||
|
||||
} // namespace webrtc
|
||||
|
@ -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<const uint32_t> csrcs);
|
||||
void Update(int64_t now_ms, rtc::ArrayView<const uint32_t> csrcs,
|
||||
absl::optional<uint8_t> audio_level);
|
||||
|
||||
// Returns contributing sources seen the last 10 s.
|
||||
std::vector<RtpSource> GetSources(int64_t now_ms) const;
|
||||
|
||||
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);
|
||||
|
||||
// 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_;
|
||||
};
|
||||
|
||||
|
@ -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
|
||||
|
@ -320,7 +320,8 @@ void RtpVideoStreamReceiver::OnRtpPacket(const RtpPacketReceived& packet) {
|
||||
last_received_rtp_system_time_ms_ = now_ms;
|
||||
|
||||
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.
|
||||
if (now_ms - last_packet_log_ms_ > kPacketLogIntervalMs) {
|
||||
|
Reference in New Issue
Block a user