blob: 74186f040c1420fd19b13c9eba26e893e3c11b6f [file] [log] [blame]
sakale5ba44e2016-10-26 07:09:24 -07001/*
2 * Copyright 2016 The WebRTC project authors. All Rights Reserved.
3 *
4 * Use of this source code is governed by a BSD-style license
5 * that can be found in the LICENSE file in the root of the source
6 * tree. An additional intellectual property rights grant can be found
7 * in the file PATENTS. All contributing project authors may
8 * be found in the AUTHORS file in the root of the source tree.
9 */
10
11#include "webrtc/video/receive_statistics_proxy.h"
12
13#include <memory>
14
asapersson0c43f772016-11-30 01:42:26 -080015#include "webrtc/system_wrappers/include/metrics.h"
asaperssonde9e5ff2016-11-02 07:14:03 -070016#include "webrtc/system_wrappers/include/metrics_default.h"
sakale5ba44e2016-10-26 07:09:24 -070017#include "webrtc/test/gtest.h"
18
19namespace webrtc {
asaperssonde9e5ff2016-11-02 07:14:03 -070020namespace {
21const int64_t kFreqOffsetProcessIntervalInMs = 40000;
asapersson46c4e3c2016-11-03 06:48:19 -070022const uint32_t kLocalSsrc = 123;
23const uint32_t kRemoteSsrc = 456;
24const int kMinRequiredSamples = 200;
asaperssonde9e5ff2016-11-02 07:14:03 -070025} // namespace
sakale5ba44e2016-10-26 07:09:24 -070026
27// TODO(sakal): ReceiveStatisticsProxy is lacking unittesting.
28class ReceiveStatisticsProxyTest : public ::testing::Test {
29 public:
30 ReceiveStatisticsProxyTest() : fake_clock_(1234), config_(GetTestConfig()) {}
31 virtual ~ReceiveStatisticsProxyTest() {}
32
33 protected:
34 virtual void SetUp() {
asaperssonde9e5ff2016-11-02 07:14:03 -070035 metrics::Reset();
sakale5ba44e2016-10-26 07:09:24 -070036 statistics_proxy_.reset(new ReceiveStatisticsProxy(&config_, &fake_clock_));
37 }
38
39 VideoReceiveStream::Config GetTestConfig() {
40 VideoReceiveStream::Config config(nullptr);
asapersson46c4e3c2016-11-03 06:48:19 -070041 config.rtp.local_ssrc = kLocalSsrc;
42 config.rtp.remote_ssrc = kRemoteSsrc;
sakale5ba44e2016-10-26 07:09:24 -070043 return config;
44 }
45
46 SimulatedClock fake_clock_;
asaperssonde9e5ff2016-11-02 07:14:03 -070047 const VideoReceiveStream::Config config_;
sakale5ba44e2016-10-26 07:09:24 -070048 std::unique_ptr<ReceiveStatisticsProxy> statistics_proxy_;
sakale5ba44e2016-10-26 07:09:24 -070049};
50
51TEST_F(ReceiveStatisticsProxyTest, OnDecodedFrameIncreasesFramesDecoded) {
52 EXPECT_EQ(0u, statistics_proxy_->GetStats().frames_decoded);
53 for (uint32_t i = 1; i <= 3; ++i) {
54 statistics_proxy_->OnDecodedFrame();
55 EXPECT_EQ(i, statistics_proxy_->GetStats().frames_decoded);
56 }
57}
58
asapersson46c4e3c2016-11-03 06:48:19 -070059TEST_F(ReceiveStatisticsProxyTest, GetStatsReportsSsrc) {
60 EXPECT_EQ(kRemoteSsrc, statistics_proxy_->GetStats().ssrc);
61}
62
63TEST_F(ReceiveStatisticsProxyTest, GetStatsReportsIncomingPayloadType) {
64 const int kPayloadType = 111;
65 statistics_proxy_->OnIncomingPayloadType(kPayloadType);
66 EXPECT_EQ(kPayloadType, statistics_proxy_->GetStats().current_payload_type);
67}
68
69TEST_F(ReceiveStatisticsProxyTest, GetStatsReportsIncomingRate) {
70 const int kFramerate = 28;
71 const int kBitrateBps = 311000;
72 statistics_proxy_->OnIncomingRate(kFramerate, kBitrateBps);
73 EXPECT_EQ(kFramerate, statistics_proxy_->GetStats().network_frame_rate);
74 EXPECT_EQ(kBitrateBps, statistics_proxy_->GetStats().total_bitrate_bps);
75}
76
77TEST_F(ReceiveStatisticsProxyTest, GetStatsReportsDecodeTimingStats) {
78 const int kDecodeMs = 1;
79 const int kMaxDecodeMs = 2;
80 const int kCurrentDelayMs = 3;
81 const int kTargetDelayMs = 4;
82 const int kJitterBufferMs = 5;
83 const int kMinPlayoutDelayMs = 6;
84 const int kRenderDelayMs = 7;
85 const int64_t kRttMs = 8;
86 statistics_proxy_->OnDecoderTiming(
87 kDecodeMs, kMaxDecodeMs, kCurrentDelayMs, kTargetDelayMs, kJitterBufferMs,
88 kMinPlayoutDelayMs, kRenderDelayMs, kRttMs);
89 VideoReceiveStream::Stats stats = statistics_proxy_->GetStats();
90 EXPECT_EQ(kDecodeMs, stats.decode_ms);
91 EXPECT_EQ(kMaxDecodeMs, stats.max_decode_ms);
92 EXPECT_EQ(kCurrentDelayMs, stats.current_delay_ms);
93 EXPECT_EQ(kTargetDelayMs, stats.target_delay_ms);
94 EXPECT_EQ(kJitterBufferMs, stats.jitter_buffer_ms);
95 EXPECT_EQ(kMinPlayoutDelayMs, stats.min_playout_delay_ms);
96 EXPECT_EQ(kRenderDelayMs, stats.render_delay_ms);
97}
98
99TEST_F(ReceiveStatisticsProxyTest, GetStatsReportsDiscardedPackets) {
100 const int kDiscardedPackets = 12;
101 statistics_proxy_->OnDiscardedPacketsUpdated(kDiscardedPackets);
102 EXPECT_EQ(kDiscardedPackets, statistics_proxy_->GetStats().discarded_packets);
103}
104
105TEST_F(ReceiveStatisticsProxyTest, LifetimeHistogramIsUpdated) {
106 const int64_t kTimeSec = 3;
107 fake_clock_.AdvanceTimeMilliseconds(kTimeSec * 1000);
108 // Histograms are updated when the statistics_proxy_ is deleted.
109 statistics_proxy_.reset();
110 EXPECT_EQ(1,
111 metrics::NumSamples("WebRTC.Video.ReceiveStreamLifetimeInSeconds"));
112 EXPECT_EQ(1, metrics::NumEvents("WebRTC.Video.ReceiveStreamLifetimeInSeconds",
113 kTimeSec));
114}
115
asapersson0c43f772016-11-30 01:42:26 -0800116TEST_F(ReceiveStatisticsProxyTest, PacketLossHistogramIsUpdated) {
117 const uint32_t kCumLost1 = 1;
118 const uint32_t kExtSeqNum1 = 10;
119 const uint32_t kCumLost2 = 2;
120 const uint32_t kExtSeqNum2 = 20;
121
122 // One report block received.
123 RtcpStatistics rtcp_stats1;
124 rtcp_stats1.cumulative_lost = kCumLost1;
125 rtcp_stats1.extended_max_sequence_number = kExtSeqNum1;
126 statistics_proxy_->StatisticsUpdated(rtcp_stats1, kRemoteSsrc);
127
128 // Two report blocks received.
129 RtcpStatistics rtcp_stats2;
130 rtcp_stats2.cumulative_lost = kCumLost2;
131 rtcp_stats2.extended_max_sequence_number = kExtSeqNum2;
132 statistics_proxy_->StatisticsUpdated(rtcp_stats2, kRemoteSsrc);
133
134 // Two received report blocks but min run time has not passed.
135 fake_clock_.AdvanceTimeMilliseconds(metrics::kMinRunTimeInSeconds * 1000 - 1);
136 SetUp(); // Reset stat proxy causes histograms to be updated.
137 EXPECT_EQ(0,
138 metrics::NumSamples("WebRTC.Video.ReceivedPacketsLostInPercent"));
139
140 // Two report blocks received.
141 statistics_proxy_->StatisticsUpdated(rtcp_stats1, kRemoteSsrc);
142 statistics_proxy_->StatisticsUpdated(rtcp_stats2, kRemoteSsrc);
143
144 // Two received report blocks and min run time has passed.
145 fake_clock_.AdvanceTimeMilliseconds(metrics::kMinRunTimeInSeconds * 1000);
146 SetUp();
147 EXPECT_EQ(1,
148 metrics::NumSamples("WebRTC.Video.ReceivedPacketsLostInPercent"));
149 EXPECT_EQ(1, metrics::NumEvents("WebRTC.Video.ReceivedPacketsLostInPercent",
150 (kCumLost2 - kCumLost1) * 100 /
151 (kExtSeqNum2 - kExtSeqNum1)));
152}
153
154TEST_F(ReceiveStatisticsProxyTest,
155 PacketLossHistogramIsNotUpdatedIfLessThanTwoReportBlocksAreReceived) {
156 RtcpStatistics rtcp_stats1;
157 rtcp_stats1.cumulative_lost = 1;
158 rtcp_stats1.extended_max_sequence_number = 10;
159
160 // Min run time has passed but no received report block.
161 fake_clock_.AdvanceTimeMilliseconds(metrics::kMinRunTimeInSeconds * 1000);
162 SetUp(); // Reset stat proxy causes histograms to be updated.
163 EXPECT_EQ(0,
164 metrics::NumSamples("WebRTC.Video.ReceivedPacketsLostInPercent"));
165
166 // Min run time has passed but only one received report block.
167 statistics_proxy_->StatisticsUpdated(rtcp_stats1, kRemoteSsrc);
168 fake_clock_.AdvanceTimeMilliseconds(metrics::kMinRunTimeInSeconds * 1000);
169 SetUp();
170 EXPECT_EQ(0,
171 metrics::NumSamples("WebRTC.Video.ReceivedPacketsLostInPercent"));
172}
173
asapersson46c4e3c2016-11-03 06:48:19 -0700174TEST_F(ReceiveStatisticsProxyTest, AvSyncOffsetHistogramIsUpdated) {
175 const int64_t kSyncOffsetMs = 22;
176 const double kFreqKhz = 90.0;
177 for (int i = 0; i < kMinRequiredSamples; ++i)
178 statistics_proxy_->OnSyncOffsetUpdated(kSyncOffsetMs, kFreqKhz);
179 // Histograms are updated when the statistics_proxy_ is deleted.
180 statistics_proxy_.reset();
181 EXPECT_EQ(1, metrics::NumSamples("WebRTC.Video.AVSyncOffsetInMs"));
182 EXPECT_EQ(1,
183 metrics::NumEvents("WebRTC.Video.AVSyncOffsetInMs", kSyncOffsetMs));
184}
185
asaperssonde9e5ff2016-11-02 07:14:03 -0700186TEST_F(ReceiveStatisticsProxyTest, RtpToNtpFrequencyOffsetHistogramIsUpdated) {
187 const int64_t kSyncOffsetMs = 22;
188 const double kFreqKhz = 90.0;
189 statistics_proxy_->OnSyncOffsetUpdated(kSyncOffsetMs, kFreqKhz);
190 statistics_proxy_->OnSyncOffsetUpdated(kSyncOffsetMs, kFreqKhz + 2.2);
191 fake_clock_.AdvanceTimeMilliseconds(kFreqOffsetProcessIntervalInMs);
192 // Process interval passed, max diff: 2.
193 statistics_proxy_->OnSyncOffsetUpdated(kSyncOffsetMs, kFreqKhz + 1.1);
194 statistics_proxy_->OnSyncOffsetUpdated(kSyncOffsetMs, kFreqKhz - 4.2);
195 statistics_proxy_->OnSyncOffsetUpdated(kSyncOffsetMs, kFreqKhz - 0.9);
196 fake_clock_.AdvanceTimeMilliseconds(kFreqOffsetProcessIntervalInMs);
197 // Process interval passed, max diff: 4.
198 statistics_proxy_->OnSyncOffsetUpdated(kSyncOffsetMs, kFreqKhz);
199 statistics_proxy_.reset();
200 // Average reported: (2 + 4) / 2 = 3.
201 EXPECT_EQ(1, metrics::NumSamples("WebRTC.Video.RtpToNtpFreqOffsetInKhz"));
202 EXPECT_EQ(1, metrics::NumEvents("WebRTC.Video.RtpToNtpFreqOffsetInKhz", 3));
203}
204
sakale5ba44e2016-10-26 07:09:24 -0700205} // namespace webrtc