Move send delay calculation to SendStatisticsProxy from RtpSenderEgress
Bug: None Change-Id: I5d14c8898d16b12062cf0b172fcc138c23d28b3b Reviewed-on: https://webrtc-review.googlesource.com/c/src/+/319562 Reviewed-by: Åsa Persson <asapersson@webrtc.org> Commit-Queue: Danil Chapovalov <danilchap@webrtc.org> Cr-Commit-Position: refs/heads/main@{#40741}
This commit is contained in:
parent
10e5724fe9
commit
652eccf552
@ -1382,20 +1382,52 @@ void SendStatisticsProxy::FrameCountUpdated(const FrameCounts& frame_counts,
|
||||
stats->frame_counts = frame_counts;
|
||||
}
|
||||
|
||||
void SendStatisticsProxy::OnSendPacket(uint32_t ssrc, Timestamp capture_time) {
|
||||
[[maybe_unused]] TimeDelta send_delay = clock_->CurrentTime() - capture_time;
|
||||
// TODO(danilchap): Calculate average and max send_delay per ssrc over last
|
||||
// second, Use that measurement instead of whatever is received in
|
||||
// SendSideDelayUpdated below.
|
||||
void SendStatisticsProxy::Trackers::AddSendDelay(Timestamp now,
|
||||
TimeDelta send_delay) {
|
||||
// Add the new measurement.
|
||||
send_delays.push_back({.when = now, .send_delay = send_delay});
|
||||
send_delay_sum += send_delay;
|
||||
if (send_delay_max == nullptr || *send_delay_max <= send_delay) {
|
||||
send_delay_max = &send_delays.back().send_delay;
|
||||
}
|
||||
|
||||
// Remove old. No need to check for emptiness because newly added entry would
|
||||
// never be too old.
|
||||
while (now - send_delays.front().when > TimeDelta::Seconds(1)) {
|
||||
send_delay_sum -= send_delays.front().send_delay;
|
||||
if (send_delay_max == &send_delays.front().send_delay) {
|
||||
send_delay_max = nullptr;
|
||||
}
|
||||
send_delays.pop_front();
|
||||
}
|
||||
|
||||
// Check if max value was pushed out from the queue as too old.
|
||||
if (send_delay_max == nullptr) {
|
||||
send_delay_max = &send_delays.front().send_delay;
|
||||
for (const SendDelayEntry& entry : send_delays) {
|
||||
// Use '>=' rather than '>' to prefer latest maximum as it would be pushed
|
||||
// out later and thus trigger less recalculations.
|
||||
if (entry.send_delay >= *send_delay_max) {
|
||||
send_delay_max = &entry.send_delay;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void SendStatisticsProxy::SendSideDelayUpdated(int avg_delay_ms,
|
||||
int max_delay_ms,
|
||||
uint32_t ssrc) {
|
||||
void SendStatisticsProxy::OnSendPacket(uint32_t ssrc, Timestamp capture_time) {
|
||||
Timestamp now = clock_->CurrentTime();
|
||||
|
||||
MutexLock lock(&mutex_);
|
||||
VideoSendStream::StreamStats* stats = GetStatsEntry(ssrc);
|
||||
if (!stats)
|
||||
return;
|
||||
|
||||
Trackers& track = trackers_[ssrc];
|
||||
track.AddSendDelay(now, now - capture_time);
|
||||
|
||||
int64_t avg_delay_ms = (track.send_delay_sum / track.send_delays.size()).ms();
|
||||
int64_t max_delay_ms = track.send_delay_max->ms();
|
||||
|
||||
stats->avg_delay_ms = avg_delay_ms;
|
||||
stats->max_delay_ms = max_delay_ms;
|
||||
|
||||
|
||||
@ -12,6 +12,7 @@
|
||||
#define VIDEO_SEND_STATISTICS_PROXY_H_
|
||||
|
||||
#include <array>
|
||||
#include <deque>
|
||||
#include <map>
|
||||
#include <memory>
|
||||
#include <string>
|
||||
@ -131,7 +132,7 @@ class SendStatisticsProxy : public VideoStreamEncoderObserver,
|
||||
// From SendSideDelayObserver.
|
||||
void SendSideDelayUpdated(int avg_delay_ms,
|
||||
int max_delay_ms,
|
||||
uint32_t ssrc) override;
|
||||
uint32_t ssrc) override {}
|
||||
|
||||
private:
|
||||
class SampleCounter {
|
||||
@ -252,12 +253,28 @@ class SendStatisticsProxy : public VideoStreamEncoderObserver,
|
||||
};
|
||||
// Collection of various stats that are tracked per ssrc.
|
||||
struct Trackers {
|
||||
struct SendDelayEntry {
|
||||
Timestamp when;
|
||||
TimeDelta send_delay;
|
||||
};
|
||||
|
||||
Trackers();
|
||||
Trackers(const Trackers&) = delete;
|
||||
Trackers& operator=(const Trackers&) = delete;
|
||||
|
||||
void AddSendDelay(Timestamp now, TimeDelta send_delay);
|
||||
|
||||
Timestamp resolution_update = Timestamp::MinusInfinity();
|
||||
rtc::RateTracker encoded_frame_rate;
|
||||
|
||||
std::deque<SendDelayEntry> send_delays;
|
||||
|
||||
// The sum of `send_delay` in `send_delays`.
|
||||
TimeDelta send_delay_sum = TimeDelta::Zero();
|
||||
|
||||
// Pointer to the maximum `send_delay` in `send_delays` or nullptr if
|
||||
// `send_delays.empty()`
|
||||
const TimeDelta* send_delay_max = nullptr;
|
||||
};
|
||||
|
||||
void SetAdaptTimer(const MaskedAdaptationCounts& counts, StatsTimer* timer)
|
||||
|
||||
@ -320,24 +320,29 @@ TEST_F(SendStatisticsProxyTest, Bitrate) {
|
||||
}
|
||||
|
||||
TEST_F(SendStatisticsProxyTest, SendSideDelay) {
|
||||
SendSideDelayObserver* observer = statistics_proxy_.get();
|
||||
for (const auto& ssrc : config_.rtp.ssrcs) {
|
||||
for (uint32_t ssrc : config_.rtp.ssrcs) {
|
||||
// Use ssrc as avg_delay_ms and max_delay_ms to get a unique value for each
|
||||
// stream.
|
||||
int avg_delay_ms = ssrc;
|
||||
int max_delay_ms = ssrc + 1;
|
||||
observer->SendSideDelayUpdated(avg_delay_ms, max_delay_ms, ssrc);
|
||||
expected_.substreams[ssrc].avg_delay_ms = avg_delay_ms;
|
||||
expected_.substreams[ssrc].max_delay_ms = max_delay_ms;
|
||||
expected_.substreams[ssrc].avg_delay_ms = ssrc;
|
||||
expected_.substreams[ssrc].max_delay_ms = ssrc + 1;
|
||||
statistics_proxy_->OnSendPacket(ssrc,
|
||||
/*capture_time=*/fake_clock_.CurrentTime() -
|
||||
TimeDelta::Millis(ssrc + 1));
|
||||
statistics_proxy_->OnSendPacket(ssrc,
|
||||
/*capture_time=*/fake_clock_.CurrentTime() -
|
||||
TimeDelta::Millis(ssrc - 1));
|
||||
}
|
||||
for (const auto& ssrc : config_.rtp.rtx.ssrcs) {
|
||||
for (uint32_t ssrc : config_.rtp.rtx.ssrcs) {
|
||||
// Use ssrc as avg_delay_ms and max_delay_ms to get a unique value for each
|
||||
// stream.
|
||||
int avg_delay_ms = ssrc;
|
||||
int max_delay_ms = ssrc + 1;
|
||||
observer->SendSideDelayUpdated(avg_delay_ms, max_delay_ms, ssrc);
|
||||
expected_.substreams[ssrc].avg_delay_ms = avg_delay_ms;
|
||||
expected_.substreams[ssrc].max_delay_ms = max_delay_ms;
|
||||
expected_.substreams[ssrc].avg_delay_ms = ssrc;
|
||||
expected_.substreams[ssrc].max_delay_ms = ssrc + 1;
|
||||
statistics_proxy_->OnSendPacket(ssrc,
|
||||
/*capture_time=*/fake_clock_.CurrentTime() -
|
||||
TimeDelta::Millis(ssrc + 1));
|
||||
statistics_proxy_->OnSendPacket(ssrc,
|
||||
/*capture_time=*/fake_clock_.CurrentTime() -
|
||||
TimeDelta::Millis(ssrc - 1));
|
||||
}
|
||||
VideoSendStream::Stats stats = statistics_proxy_->GetStats();
|
||||
ExpectEqual(expected_, stats);
|
||||
|
||||
@ -101,7 +101,7 @@ RtpSenderObservers CreateObservers(RtcpRttStats* call_stats,
|
||||
observers.bitrate_observer = stats_proxy;
|
||||
observers.frame_count_observer = stats_proxy;
|
||||
observers.rtcp_type_observer = stats_proxy;
|
||||
observers.send_delay_observer = stats_proxy;
|
||||
observers.send_delay_observer = nullptr;
|
||||
observers.send_packet_observer = send_packet_observer;
|
||||
return observers;
|
||||
}
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user