Add average rtt to CallStatsObserver and an average rtt histogram.

TBR=mflodman@webrtc.org

BUG=webrtc:4711,webrtc:4548

Review URL: https://codereview.webrtc.org/1279543005

Cr-Commit-Position: refs/heads/master@{#9687}
This commit is contained in:
stefan 2015-08-07 04:27:51 -07:00 committed by Commit bot
parent 0482dcc873
commit 2328a94ec7
12 changed files with 65 additions and 54 deletions

View File

@ -440,7 +440,7 @@ struct FecProtectionParams {
// CallStats object using RegisterStatsObserver.
class CallStatsObserver {
public:
virtual void OnRttUpdate(int64_t rtt_ms) = 0;
virtual void OnRttUpdate(int64_t avg_rtt_ms, int64_t max_rtt_ms) = 0;
virtual ~CallStatsObserver() {}
};

View File

@ -372,9 +372,10 @@ void RemoteBitrateEstimatorAbsSendTime::UpdateEstimate(int64_t now_ms) {
}
}
void RemoteBitrateEstimatorAbsSendTime::OnRttUpdate(int64_t rtt) {
void RemoteBitrateEstimatorAbsSendTime::OnRttUpdate(int64_t avg_rtt_ms,
int64_t max_rtt_ms) {
CriticalSectionScoped cs(crit_sect_.get());
remote_rate_.SetRtt(rtt);
remote_rate_.SetRtt(avg_rtt_ms);
}
void RemoteBitrateEstimatorAbsSendTime::RemoveStream(unsigned int ssrc) {

View File

@ -83,7 +83,7 @@ class RemoteBitrateEstimatorAbsSendTime : public RemoteBitrateEstimator {
// deleted.
int32_t Process() override;
int64_t TimeUntilNextProcess() override;
void OnRttUpdate(int64_t rtt) override;
void OnRttUpdate(int64_t avg_rtt_ms, int64_t max_rtt_ms) override;
void RemoveStream(unsigned int ssrc) override;
bool LatestEstimate(std::vector<unsigned int>* ssrcs,
unsigned int* bitrate_bps) const override;

View File

@ -182,9 +182,10 @@ void RemoteBitrateEstimatorSingleStream::UpdateEstimate(int64_t now_ms) {
}
}
void RemoteBitrateEstimatorSingleStream::OnRttUpdate(int64_t rtt) {
void RemoteBitrateEstimatorSingleStream::OnRttUpdate(int64_t avg_rtt_ms,
int64_t max_rtt_ms) {
CriticalSectionScoped cs(crit_sect_.get());
remote_rate_->SetRtt(rtt);
remote_rate_->SetRtt(avg_rtt_ms);
}
void RemoteBitrateEstimatorSingleStream::RemoveStream(unsigned int ssrc) {

View File

@ -34,7 +34,7 @@ class RemoteBitrateEstimatorSingleStream : public RemoteBitrateEstimator {
bool was_paced) override;
int32_t Process() override;
int64_t TimeUntilNextProcess() override;
void OnRttUpdate(int64_t rtt) override;
void OnRttUpdate(int64_t avg_rtt_ms, int64_t max_rtt_ms) override;
void RemoveStream(unsigned int ssrc) override;
bool LatestEstimate(std::vector<unsigned int>* ssrcs,
unsigned int* bitrate_bps) const override;

View File

@ -77,7 +77,7 @@ RembReceiver::RembReceiver(int flow_id, bool plot)
ss << "Estimate_" << flow_id_ << "#1";
estimate_log_prefix_ = ss.str();
// Default RTT in RemoteRateControl is 200 ms ; 50 ms is more realistic.
estimator_->OnRttUpdate(50);
estimator_->OnRttUpdate(50, 50);
}
RembReceiver::~RembReceiver() {

View File

@ -61,7 +61,7 @@ void FullBweSender::GiveFeedback(const FeedbackPacket& feedback) {
int64_t rtt_ms =
clock_->TimeInMilliseconds() - feedback.latest_send_time_ms();
rbe_->OnRttUpdate(rtt_ms);
rbe_->OnRttUpdate(rtt_ms, rtt_ms);
BWE_TEST_LOGGING_PLOT(1, "RTT", clock_->TimeInMilliseconds(), rtt_ms);
rbe_->IncomingPacketFeedbackVector(packet_feedback_vector);

View File

@ -123,7 +123,7 @@ int32_t CallStats::Process() {
if (max_rtt_ms_ > 0) {
for (std::list<CallStatsObserver*>::iterator it = observers_.begin();
it != observers_.end(); ++it) {
(*it)->OnRttUpdate(max_rtt_ms_);
(*it)->OnRttUpdate(avg_rtt_ms_, max_rtt_ms_);
}
}
return 0;

View File

@ -27,7 +27,7 @@ class MockStatsObserver : public CallStatsObserver {
MockStatsObserver() {}
virtual ~MockStatsObserver() {}
MOCK_METHOD1(OnRttUpdate, void(int64_t));
MOCK_METHOD2(OnRttUpdate, void(int64_t, int64_t));
};
class CallStatsTest : public ::testing::Test {
@ -48,15 +48,13 @@ TEST_F(CallStatsTest, AddAndTriggerCallback) {
const int64_t kRtt = 25;
rtcp_rtt_stats->OnRttUpdate(kRtt);
EXPECT_CALL(stats_observer, OnRttUpdate(kRtt))
.Times(1);
EXPECT_CALL(stats_observer, OnRttUpdate(kRtt, kRtt)).Times(1);
call_stats_->Process();
EXPECT_EQ(kRtt, rtcp_rtt_stats->LastProcessedRtt());
const int64_t kRttTimeOutMs = 1500 + 10;
TickTime::AdvanceFakeClock(kRttTimeOutMs);
EXPECT_CALL(stats_observer, OnRttUpdate(_))
.Times(0);
EXPECT_CALL(stats_observer, OnRttUpdate(_, _)).Times(0);
call_stats_->Process();
EXPECT_EQ(0, rtcp_rtt_stats->LastProcessedRtt());
@ -70,27 +68,23 @@ TEST_F(CallStatsTest, ProcessTime) {
rtcp_rtt_stats->OnRttUpdate(100);
// Time isn't updated yet.
EXPECT_CALL(stats_observer, OnRttUpdate(_))
.Times(0);
EXPECT_CALL(stats_observer, OnRttUpdate(_, _)).Times(0);
call_stats_->Process();
// Advance clock and verify we get an update.
TickTime::AdvanceFakeClock(1000);
EXPECT_CALL(stats_observer, OnRttUpdate(_))
.Times(1);
EXPECT_CALL(stats_observer, OnRttUpdate(_, _)).Times(1);
call_stats_->Process();
// Advance clock just too little to get an update.
TickTime::AdvanceFakeClock(999);
rtcp_rtt_stats->OnRttUpdate(100);
EXPECT_CALL(stats_observer, OnRttUpdate(_))
.Times(0);
EXPECT_CALL(stats_observer, OnRttUpdate(_, _)).Times(0);
call_stats_->Process();
// Advance enough to trigger a new update.
TickTime::AdvanceFakeClock(1);
EXPECT_CALL(stats_observer, OnRttUpdate(_))
.Times(1);
EXPECT_CALL(stats_observer, OnRttUpdate(_, _)).Times(1);
call_stats_->Process();
call_stats_->DeregisterStatsObserver(&stats_observer);
@ -113,10 +107,8 @@ TEST_F(CallStatsTest, MultipleObservers) {
// Verify both observers are updated.
TickTime::AdvanceFakeClock(1000);
EXPECT_CALL(stats_observer_1, OnRttUpdate(kRtt))
.Times(1);
EXPECT_CALL(stats_observer_2, OnRttUpdate(kRtt))
.Times(1);
EXPECT_CALL(stats_observer_1, OnRttUpdate(kRtt, kRtt)).Times(1);
EXPECT_CALL(stats_observer_2, OnRttUpdate(kRtt, kRtt)).Times(1);
call_stats_->Process();
// Deregister the second observer and verify update is only sent to the first
@ -124,20 +116,16 @@ TEST_F(CallStatsTest, MultipleObservers) {
call_stats_->DeregisterStatsObserver(&stats_observer_2);
rtcp_rtt_stats->OnRttUpdate(kRtt);
TickTime::AdvanceFakeClock(1000);
EXPECT_CALL(stats_observer_1, OnRttUpdate(kRtt))
.Times(1);
EXPECT_CALL(stats_observer_2, OnRttUpdate(kRtt))
.Times(0);
EXPECT_CALL(stats_observer_1, OnRttUpdate(kRtt, kRtt)).Times(1);
EXPECT_CALL(stats_observer_2, OnRttUpdate(kRtt, kRtt)).Times(0);
call_stats_->Process();
// Deregister the first observer.
call_stats_->DeregisterStatsObserver(&stats_observer_1);
rtcp_rtt_stats->OnRttUpdate(kRtt);
TickTime::AdvanceFakeClock(1000);
EXPECT_CALL(stats_observer_1, OnRttUpdate(kRtt))
.Times(0);
EXPECT_CALL(stats_observer_2, OnRttUpdate(kRtt))
.Times(0);
EXPECT_CALL(stats_observer_1, OnRttUpdate(kRtt, kRtt)).Times(0);
EXPECT_CALL(stats_observer_2, OnRttUpdate(kRtt, kRtt)).Times(0);
call_stats_->Process();
}
@ -153,16 +141,15 @@ TEST_F(CallStatsTest, ChangeRtt) {
// Set a first value and verify the callback is triggered.
const int64_t kFirstRtt = 100;
rtcp_rtt_stats->OnRttUpdate(kFirstRtt);
EXPECT_CALL(stats_observer, OnRttUpdate(kFirstRtt))
.Times(1);
EXPECT_CALL(stats_observer, OnRttUpdate(kFirstRtt, kFirstRtt)).Times(1);
call_stats_->Process();
// Increase rtt and verify the new value is reported.
TickTime::AdvanceFakeClock(1000);
const int64_t kHighRtt = kFirstRtt + 20;
const int64_t kAvgRtt1 = 103;
rtcp_rtt_stats->OnRttUpdate(kHighRtt);
EXPECT_CALL(stats_observer, OnRttUpdate(kHighRtt))
.Times(1);
EXPECT_CALL(stats_observer, OnRttUpdate(kAvgRtt1, kHighRtt)).Times(1);
call_stats_->Process();
// Increase time enough for a new update, but not too much to make the
@ -170,16 +157,16 @@ TEST_F(CallStatsTest, ChangeRtt) {
// in the callback.
TickTime::AdvanceFakeClock(1000);
const int64_t kLowRtt = kFirstRtt - 20;
const int64_t kAvgRtt2 = 102;
rtcp_rtt_stats->OnRttUpdate(kLowRtt);
EXPECT_CALL(stats_observer, OnRttUpdate(kHighRtt))
.Times(1);
EXPECT_CALL(stats_observer, OnRttUpdate(kAvgRtt2, kHighRtt)).Times(1);
call_stats_->Process();
// Advance time to make the high report invalid, the lower rtt should now be
// in the callback.
TickTime::AdvanceFakeClock(1000);
EXPECT_CALL(stats_observer, OnRttUpdate(kLowRtt))
.Times(1);
const int64_t kAvgRtt3 = 95;
EXPECT_CALL(stats_observer, OnRttUpdate(kAvgRtt3, kLowRtt)).Times(1);
call_stats_->Process();
call_stats_->DeregisterStatsObserver(&stats_observer);
@ -198,8 +185,7 @@ TEST_F(CallStatsTest, LastProcessedRtt) {
const int64_t kAvgRtt = 20;
rtcp_rtt_stats->OnRttUpdate(kRttLow);
rtcp_rtt_stats->OnRttUpdate(kRttHigh);
EXPECT_CALL(stats_observer, OnRttUpdate(kRttHigh))
.Times(1);
EXPECT_CALL(stats_observer, OnRttUpdate(kAvgRtt, kRttHigh)).Times(1);
call_stats_->Process();
EXPECT_EQ(kAvgRtt, rtcp_rtt_stats->LastProcessedRtt());
@ -207,8 +193,7 @@ TEST_F(CallStatsTest, LastProcessedRtt) {
TickTime::AdvanceFakeClock(1000);
rtcp_rtt_stats->OnRttUpdate(kRttLow);
rtcp_rtt_stats->OnRttUpdate(kRttHigh);
EXPECT_CALL(stats_observer, OnRttUpdate(kRttHigh))
.Times(1);
EXPECT_CALL(stats_observer, OnRttUpdate(kAvgRtt, kRttHigh)).Times(1);
call_stats_->Process();
EXPECT_EQ(kAvgRtt, rtcp_rtt_stats->LastProcessedRtt());

View File

@ -49,8 +49,8 @@ class ChannelStatsObserver : public CallStatsObserver {
virtual ~ChannelStatsObserver() {}
// Implements StatsObserver.
virtual void OnRttUpdate(int64_t rtt) {
owner_->OnRttUpdate(rtt);
virtual void OnRttUpdate(int64_t avg_rtt_ms, int64_t max_rtt_ms) {
owner_->OnRttUpdate(avg_rtt_ms, max_rtt_ms);
}
private:
@ -119,6 +119,9 @@ ViEChannel::ViEChannel(int32_t channel_id,
max_nack_reordering_threshold_(kMaxPacketAgeToNack),
pre_render_callback_(NULL),
report_block_stats_sender_(new ReportBlockStats()),
time_of_first_rtt_ms_(-1),
rtt_sum_ms_(0),
num_rtts_(0),
rtp_rtcp_modules_(
CreateRtpRtcpModules(ViEModuleId(engine_id_, channel_id_),
!sender,
@ -198,6 +201,17 @@ ViEChannel::~ViEChannel() {
void ViEChannel::UpdateHistograms() {
int64_t now = Clock::GetRealTimeClock()->TimeInMilliseconds();
{
CriticalSectionScoped cs(crit_.get());
int64_t elapsed_sec = (now - time_of_first_rtt_ms_) / 1000;
if (time_of_first_rtt_ms_ != -1 && num_rtts_ > 0 &&
elapsed_sec > metrics::kMinRunTimeInSeconds) {
int64_t avg_rtt_ms = (rtt_sum_ms_ + num_rtts_ / 2) / num_rtts_;
RTC_HISTOGRAM_COUNTS_10000(
"WebRTC.Video.AverageRoundTripTimeInMilliseconds", avg_rtt_ms);
}
}
if (sender_) {
RtcpPacketTypeCounter rtcp_counter;
GetSendRtcpPacketTypeCounter(&rtcp_counter);
@ -1119,8 +1133,14 @@ bool ViEChannel::ChannelDecodeProcess() {
return true;
}
void ViEChannel::OnRttUpdate(int64_t rtt) {
vcm_->SetReceiveChannelParameters(rtt);
void ViEChannel::OnRttUpdate(int64_t avg_rtt_ms, int64_t max_rtt_ms) {
vcm_->SetReceiveChannelParameters(max_rtt_ms);
CriticalSectionScoped cs(crit_.get());
if (time_of_first_rtt_ms_ == -1)
time_of_first_rtt_ms_ = Clock::GetRealTimeClock()->TimeInMilliseconds();
rtt_sum_ms_ += avg_rtt_ms;
++num_rtts_;
}
int ViEChannel::ProtectionRequest(const FecProtectionParams* delta_fec_params,

View File

@ -318,7 +318,7 @@ class ViEChannel : public VCMFrameTypeCallback,
static bool ChannelDecodeThreadFunction(void* obj);
bool ChannelDecodeProcess();
void OnRttUpdate(int64_t rtt);
void OnRttUpdate(int64_t avg_rtt_ms, int64_t max_rtt_ms);
int ProtectionRequest(const FecProtectionParams* delta_fec_params,
const FecProtectionParams* key_fec_params,
@ -488,6 +488,10 @@ class ViEChannel : public VCMFrameTypeCallback,
const rtc::scoped_ptr<ReportBlockStats> report_block_stats_sender_;
int64_t time_of_first_rtt_ms_ GUARDED_BY(crit_);
int64_t rtt_sum_ms_ GUARDED_BY(crit_);
size_t num_rtts_ GUARDED_BY(crit_);
// RtpRtcp modules, declared last as they use other members on construction.
const std::vector<RtpRtcp*> rtp_rtcp_modules_;
size_t num_active_rtp_rtcp_modules_ GUARDED_BY(crit_);

View File

@ -70,9 +70,9 @@ class WrappingBitrateEstimator : public RemoteBitrateEstimator {
return rbe_->TimeUntilNextProcess();
}
void OnRttUpdate(int64_t rtt) override {
void OnRttUpdate(int64_t avg_rtt_ms, int64_t max_rtt_ms) override {
CriticalSectionScoped cs(crit_sect_.get());
rbe_->OnRttUpdate(rtt);
rbe_->OnRttUpdate(avg_rtt_ms, max_rtt_ms);
}
void RemoveStream(unsigned int ssrc) override {