xref: /aosp_15_r20/external/webrtc/video/send_statistics_proxy_unittest.cc (revision d9f758449e529ab9291ac668be2861e7a55c2422)
1 /*
2  *  Copyright (c) 2013 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 "video/send_statistics_proxy.h"
12 
13 #include <algorithm>
14 #include <map>
15 #include <memory>
16 #include <string>
17 #include <vector>
18 
19 #include "absl/algorithm/container.h"
20 #include "api/units/timestamp.h"
21 #include "api/video/video_adaptation_reason.h"
22 #include "api/video/video_bitrate_allocation.h"
23 #include "api/video/video_codec_type.h"
24 #include "api/video_codecs/video_codec.h"
25 #include "rtc_base/fake_clock.h"
26 #include "system_wrappers/include/metrics.h"
27 #include "test/gmock.h"
28 #include "test/gtest.h"
29 #include "test/scoped_key_value_config.h"
30 #include "video/config/video_encoder_config.h"
31 #include "video/video_stream_encoder_observer.h"
32 
33 namespace webrtc {
34 namespace {
35 const uint32_t kFirstSsrc = 17;
36 const uint32_t kSecondSsrc = 42;
37 const uint32_t kFirstRtxSsrc = 18;
38 const uint32_t kSecondRtxSsrc = 43;
39 const uint32_t kFlexFecSsrc = 55;
40 const int kFpsPeriodicIntervalMs = 2000;
41 const int kWidth = 640;
42 const int kHeight = 480;
43 const int kQpIdx0 = 21;
44 const int kQpIdx1 = 39;
45 const int kRtpClockRateHz = 90000;
__anon9d468acb0202() 46 const CodecSpecificInfo kDefaultCodecInfo = []() {
47   CodecSpecificInfo codec_info;
48   codec_info.codecType = kVideoCodecVP8;
49   return codec_info;
50 }();
51 
52 const VideoStreamEncoderObserver::AdaptationSettings kScalingEnabled(true,
53                                                                      true);
54 const VideoStreamEncoderObserver::AdaptationSettings kFramerateScalingDisabled(
55     true,
56     false);
57 const VideoStreamEncoderObserver::AdaptationSettings kResolutionScalingDisabled(
58     false,
59     true);
60 const VideoStreamEncoderObserver::AdaptationSettings kScalingDisabled;
61 }  // namespace
62 
63 class SendStatisticsProxyTest : public ::testing::Test {
64  public:
SendStatisticsProxyTest()65   SendStatisticsProxyTest() : SendStatisticsProxyTest("") {}
SendStatisticsProxyTest(const std::string & field_trials)66   explicit SendStatisticsProxyTest(const std::string& field_trials)
67       : override_field_trials_(field_trials),
68         fake_clock_(1234),
69         config_(GetTestConfig()) {}
~SendStatisticsProxyTest()70   virtual ~SendStatisticsProxyTest() {}
71 
72  protected:
SetUp()73   virtual void SetUp() {
74     metrics::Reset();
75     statistics_proxy_.reset(
76         new SendStatisticsProxy(&fake_clock_, GetTestConfig(),
77                                 VideoEncoderConfig::ContentType::kRealtimeVideo,
78                                 override_field_trials_));
79     expected_ = VideoSendStream::Stats();
80     for (const auto& ssrc : config_.rtp.ssrcs) {
81       expected_.substreams[ssrc].type =
82           VideoSendStream::StreamStats::StreamType::kMedia;
83     }
84     for (size_t i = 0; i < config_.rtp.rtx.ssrcs.size(); ++i) {
85       uint32_t ssrc = config_.rtp.rtx.ssrcs[i];
86       expected_.substreams[ssrc].type =
87           VideoSendStream::StreamStats::StreamType::kRtx;
88       expected_.substreams[ssrc].referenced_media_ssrc = config_.rtp.ssrcs[i];
89     }
90   }
91 
GetTestConfig()92   VideoSendStream::Config GetTestConfig() {
93     VideoSendStream::Config config(nullptr);
94     config.rtp.ssrcs.push_back(kFirstSsrc);
95     config.rtp.ssrcs.push_back(kSecondSsrc);
96     config.rtp.rtx.ssrcs.push_back(kFirstRtxSsrc);
97     config.rtp.rtx.ssrcs.push_back(kSecondRtxSsrc);
98     config.rtp.ulpfec.red_payload_type = 17;
99     return config;
100   }
101 
GetTestConfigWithFlexFec()102   VideoSendStream::Config GetTestConfigWithFlexFec() {
103     VideoSendStream::Config config(nullptr);
104     config.rtp.ssrcs.push_back(kFirstSsrc);
105     config.rtp.ssrcs.push_back(kSecondSsrc);
106     config.rtp.rtx.ssrcs.push_back(kFirstRtxSsrc);
107     config.rtp.rtx.ssrcs.push_back(kSecondRtxSsrc);
108     config.rtp.flexfec.payload_type = 50;
109     config.rtp.flexfec.ssrc = kFlexFecSsrc;
110     config.rtp.flexfec.protected_media_ssrcs = {kFirstSsrc};
111     return config;
112   }
113 
GetStreamStats(uint32_t ssrc)114   VideoSendStream::StreamStats GetStreamStats(uint32_t ssrc) {
115     VideoSendStream::Stats stats = statistics_proxy_->GetStats();
116     std::map<uint32_t, VideoSendStream::StreamStats>::iterator it =
117         stats.substreams.find(ssrc);
118     EXPECT_NE(it, stats.substreams.end());
119     return it->second;
120   }
121 
UpdateDataCounters(uint32_t ssrc)122   void UpdateDataCounters(uint32_t ssrc) {
123     StreamDataCountersCallback* proxy =
124         static_cast<StreamDataCountersCallback*>(statistics_proxy_.get());
125     StreamDataCounters counters;
126     proxy->DataCountersUpdated(counters, ssrc);
127   }
128 
ExpectEqual(VideoSendStream::Stats one,VideoSendStream::Stats other)129   void ExpectEqual(VideoSendStream::Stats one, VideoSendStream::Stats other) {
130     EXPECT_EQ(one.frames, other.frames);
131     EXPECT_EQ(one.input_frame_rate, other.input_frame_rate);
132     EXPECT_EQ(one.encode_frame_rate, other.encode_frame_rate);
133     EXPECT_EQ(one.media_bitrate_bps, other.media_bitrate_bps);
134     EXPECT_EQ(one.suspended, other.suspended);
135 
136     EXPECT_EQ(one.substreams.size(), other.substreams.size());
137     for (std::map<uint32_t, VideoSendStream::StreamStats>::const_iterator it =
138              one.substreams.begin();
139          it != one.substreams.end(); ++it) {
140       std::map<uint32_t, VideoSendStream::StreamStats>::const_iterator
141           corresponding_it = other.substreams.find(it->first);
142       ASSERT_TRUE(corresponding_it != other.substreams.end());
143       const VideoSendStream::StreamStats& a = it->second;
144       const VideoSendStream::StreamStats& b = corresponding_it->second;
145 
146       EXPECT_EQ(a.type, b.type);
147       EXPECT_EQ(a.frame_counts.key_frames, b.frame_counts.key_frames);
148       EXPECT_EQ(a.frame_counts.delta_frames, b.frame_counts.delta_frames);
149       EXPECT_EQ(a.total_bitrate_bps, b.total_bitrate_bps);
150       EXPECT_EQ(a.avg_delay_ms, b.avg_delay_ms);
151       EXPECT_EQ(a.max_delay_ms, b.max_delay_ms);
152 
153       EXPECT_EQ(a.rtp_stats.transmitted.payload_bytes,
154                 b.rtp_stats.transmitted.payload_bytes);
155       EXPECT_EQ(a.rtp_stats.transmitted.header_bytes,
156                 b.rtp_stats.transmitted.header_bytes);
157       EXPECT_EQ(a.rtp_stats.transmitted.padding_bytes,
158                 b.rtp_stats.transmitted.padding_bytes);
159       EXPECT_EQ(a.rtp_stats.transmitted.packets,
160                 b.rtp_stats.transmitted.packets);
161       EXPECT_EQ(a.rtp_stats.retransmitted.packets,
162                 b.rtp_stats.retransmitted.packets);
163       EXPECT_EQ(a.rtp_stats.fec.packets, b.rtp_stats.fec.packets);
164 
165       EXPECT_EQ(a.report_block_data.has_value(),
166                 b.report_block_data.has_value());
167       if (a.report_block_data.has_value()) {
168         const RTCPReportBlock& a_rtcp_stats =
169             a.report_block_data->report_block();
170         const RTCPReportBlock& b_rtcp_stats =
171             b.report_block_data->report_block();
172         EXPECT_EQ(a_rtcp_stats.fraction_lost, b_rtcp_stats.fraction_lost);
173         EXPECT_EQ(a_rtcp_stats.packets_lost, b_rtcp_stats.packets_lost);
174         EXPECT_EQ(a_rtcp_stats.extended_highest_sequence_number,
175                   b_rtcp_stats.extended_highest_sequence_number);
176         EXPECT_EQ(a_rtcp_stats.jitter, b_rtcp_stats.jitter);
177       }
178     }
179   }
180 
181   test::ScopedKeyValueConfig override_field_trials_;
182   SimulatedClock fake_clock_;
183   std::unique_ptr<SendStatisticsProxy> statistics_proxy_;
184   VideoSendStream::Config config_;
185   VideoSendStream::Stats expected_;
186 };
187 
TEST_F(SendStatisticsProxyTest,ReportBlockDataObserver)188 TEST_F(SendStatisticsProxyTest, ReportBlockDataObserver) {
189   ReportBlockDataObserver* callback = statistics_proxy_.get();
190   for (uint32_t ssrc : config_.rtp.ssrcs) {
191     // Add statistics with some arbitrary, but unique, numbers.
192     uint32_t offset = ssrc * 4;
193     RTCPReportBlock report_block;
194     report_block.source_ssrc = ssrc;
195     report_block.packets_lost = offset;
196     report_block.extended_highest_sequence_number = offset + 1;
197     report_block.fraction_lost = offset + 2;
198     report_block.jitter = offset + 3;
199     ReportBlockData data;
200     data.SetReportBlock(report_block, 0);
201     expected_.substreams[ssrc].report_block_data = data;
202 
203     callback->OnReportBlockDataUpdated(data);
204   }
205   for (uint32_t ssrc : config_.rtp.rtx.ssrcs) {
206     // Add statistics with some arbitrary, but unique, numbers.
207     uint32_t offset = ssrc * 4;
208     RTCPReportBlock report_block;
209     report_block.source_ssrc = ssrc;
210     report_block.packets_lost = offset;
211     report_block.extended_highest_sequence_number = offset + 1;
212     report_block.fraction_lost = offset + 2;
213     report_block.jitter = offset + 3;
214     ReportBlockData data;
215     data.SetReportBlock(report_block, 0);
216     expected_.substreams[ssrc].report_block_data = data;
217 
218     callback->OnReportBlockDataUpdated(data);
219   }
220   VideoSendStream::Stats stats = statistics_proxy_->GetStats();
221   ExpectEqual(expected_, stats);
222 }
223 
TEST_F(SendStatisticsProxyTest,Suspended)224 TEST_F(SendStatisticsProxyTest, Suspended) {
225   // Verify that the value is false by default.
226   EXPECT_FALSE(statistics_proxy_->GetStats().suspended);
227 
228   // Verify that we can set it to true.
229   statistics_proxy_->OnSuspendChange(true);
230   EXPECT_TRUE(statistics_proxy_->GetStats().suspended);
231 
232   // Verify that we can set it back to false again.
233   statistics_proxy_->OnSuspendChange(false);
234   EXPECT_FALSE(statistics_proxy_->GetStats().suspended);
235 }
236 
TEST_F(SendStatisticsProxyTest,FrameCounts)237 TEST_F(SendStatisticsProxyTest, FrameCounts) {
238   FrameCountObserver* observer = statistics_proxy_.get();
239   for (const auto& ssrc : config_.rtp.ssrcs) {
240     // Add statistics with some arbitrary, but unique, numbers.
241     VideoSendStream::StreamStats& stats = expected_.substreams[ssrc];
242     uint32_t offset = ssrc * sizeof(VideoSendStream::StreamStats);
243     FrameCounts frame_counts;
244     frame_counts.key_frames = offset;
245     frame_counts.delta_frames = offset + 1;
246     stats.frame_counts = frame_counts;
247     observer->FrameCountUpdated(frame_counts, ssrc);
248   }
249   for (const auto& ssrc : config_.rtp.rtx.ssrcs) {
250     // Add statistics with some arbitrary, but unique, numbers.
251     VideoSendStream::StreamStats& stats = expected_.substreams[ssrc];
252     uint32_t offset = ssrc * sizeof(VideoSendStream::StreamStats);
253     FrameCounts frame_counts;
254     frame_counts.key_frames = offset;
255     frame_counts.delta_frames = offset + 1;
256     stats.frame_counts = frame_counts;
257     observer->FrameCountUpdated(frame_counts, ssrc);
258   }
259 
260   VideoSendStream::Stats stats = statistics_proxy_->GetStats();
261   ExpectEqual(expected_, stats);
262 }
263 
TEST_F(SendStatisticsProxyTest,DataCounters)264 TEST_F(SendStatisticsProxyTest, DataCounters) {
265   StreamDataCountersCallback* callback = statistics_proxy_.get();
266   for (const auto& ssrc : config_.rtp.ssrcs) {
267     StreamDataCounters& counters = expected_.substreams[ssrc].rtp_stats;
268     // Add statistics with some arbitrary, but unique, numbers.
269     size_t offset = ssrc * sizeof(StreamDataCounters);
270     uint32_t offset_uint32 = static_cast<uint32_t>(offset);
271     counters.transmitted.payload_bytes = offset;
272     counters.transmitted.header_bytes = offset + 1;
273     counters.fec.packets = offset_uint32 + 2;
274     counters.transmitted.padding_bytes = offset + 3;
275     counters.retransmitted.packets = offset_uint32 + 4;
276     counters.transmitted.packets = offset_uint32 + 5;
277     callback->DataCountersUpdated(counters, ssrc);
278   }
279   for (const auto& ssrc : config_.rtp.rtx.ssrcs) {
280     StreamDataCounters& counters = expected_.substreams[ssrc].rtp_stats;
281     // Add statistics with some arbitrary, but unique, numbers.
282     size_t offset = ssrc * sizeof(StreamDataCounters);
283     uint32_t offset_uint32 = static_cast<uint32_t>(offset);
284     counters.transmitted.payload_bytes = offset;
285     counters.transmitted.header_bytes = offset + 1;
286     counters.fec.packets = offset_uint32 + 2;
287     counters.transmitted.padding_bytes = offset + 3;
288     counters.retransmitted.packets = offset_uint32 + 4;
289     counters.transmitted.packets = offset_uint32 + 5;
290     callback->DataCountersUpdated(counters, ssrc);
291   }
292 
293   VideoSendStream::Stats stats = statistics_proxy_->GetStats();
294   ExpectEqual(expected_, stats);
295 }
296 
TEST_F(SendStatisticsProxyTest,Bitrate)297 TEST_F(SendStatisticsProxyTest, Bitrate) {
298   BitrateStatisticsObserver* observer = statistics_proxy_.get();
299   for (const auto& ssrc : config_.rtp.ssrcs) {
300     // Use ssrc as bitrate_bps to get a unique value for each stream.
301     uint32_t total = ssrc;
302     uint32_t retransmit = ssrc + 1;
303     observer->Notify(total, retransmit, ssrc);
304     expected_.substreams[ssrc].total_bitrate_bps = total;
305     expected_.substreams[ssrc].retransmit_bitrate_bps = retransmit;
306   }
307   for (const auto& ssrc : config_.rtp.rtx.ssrcs) {
308     // Use ssrc as bitrate_bps to get a unique value for each stream.
309     uint32_t total = ssrc;
310     uint32_t retransmit = ssrc + 1;
311     observer->Notify(total, retransmit, ssrc);
312     expected_.substreams[ssrc].total_bitrate_bps = total;
313     expected_.substreams[ssrc].retransmit_bitrate_bps = retransmit;
314   }
315 
316   VideoSendStream::Stats stats = statistics_proxy_->GetStats();
317   ExpectEqual(expected_, stats);
318 }
319 
TEST_F(SendStatisticsProxyTest,SendSideDelay)320 TEST_F(SendStatisticsProxyTest, SendSideDelay) {
321   SendSideDelayObserver* observer = statistics_proxy_.get();
322   for (const auto& ssrc : config_.rtp.ssrcs) {
323     // Use ssrc as avg_delay_ms and max_delay_ms to get a unique value for each
324     // stream.
325     int avg_delay_ms = ssrc;
326     int max_delay_ms = ssrc + 1;
327     observer->SendSideDelayUpdated(avg_delay_ms, max_delay_ms, ssrc);
328     expected_.substreams[ssrc].avg_delay_ms = avg_delay_ms;
329     expected_.substreams[ssrc].max_delay_ms = max_delay_ms;
330   }
331   for (const auto& ssrc : config_.rtp.rtx.ssrcs) {
332     // Use ssrc as avg_delay_ms and max_delay_ms to get a unique value for each
333     // stream.
334     int avg_delay_ms = ssrc;
335     int max_delay_ms = ssrc + 1;
336     observer->SendSideDelayUpdated(avg_delay_ms, max_delay_ms, ssrc);
337     expected_.substreams[ssrc].avg_delay_ms = avg_delay_ms;
338     expected_.substreams[ssrc].max_delay_ms = max_delay_ms;
339   }
340   VideoSendStream::Stats stats = statistics_proxy_->GetStats();
341   ExpectEqual(expected_, stats);
342 }
343 
TEST_F(SendStatisticsProxyTest,OnEncodedFrameTimeMeasured)344 TEST_F(SendStatisticsProxyTest, OnEncodedFrameTimeMeasured) {
345   const int kEncodeTimeMs = 11;
346   int encode_usage_percent = 80;
347   statistics_proxy_->OnEncodedFrameTimeMeasured(kEncodeTimeMs,
348                                                 encode_usage_percent);
349 
350   VideoSendStream::Stats stats = statistics_proxy_->GetStats();
351   EXPECT_EQ(kEncodeTimeMs, stats.avg_encode_time_ms);
352   EXPECT_EQ(encode_usage_percent, stats.encode_usage_percent);
353 }
354 
TEST_F(SendStatisticsProxyTest,TotalEncodeTimeIncreasesPerFrameMeasured)355 TEST_F(SendStatisticsProxyTest, TotalEncodeTimeIncreasesPerFrameMeasured) {
356   const int kEncodeUsagePercent = 0;  // Don't care for this test.
357   EXPECT_EQ(0u, statistics_proxy_->GetStats().total_encode_time_ms);
358   statistics_proxy_->OnEncodedFrameTimeMeasured(10, kEncodeUsagePercent);
359   EXPECT_EQ(10u, statistics_proxy_->GetStats().total_encode_time_ms);
360   statistics_proxy_->OnEncodedFrameTimeMeasured(20, kEncodeUsagePercent);
361   EXPECT_EQ(30u, statistics_proxy_->GetStats().total_encode_time_ms);
362 }
363 
TEST_F(SendStatisticsProxyTest,OnSendEncodedImageIncreasesFramesEncoded)364 TEST_F(SendStatisticsProxyTest, OnSendEncodedImageIncreasesFramesEncoded) {
365   EncodedImage encoded_image;
366   CodecSpecificInfo codec_info;
367   EXPECT_EQ(0u, statistics_proxy_->GetStats().frames_encoded);
368   for (uint32_t i = 1; i <= 3; ++i) {
369     statistics_proxy_->OnSendEncodedImage(encoded_image, &codec_info);
370     EXPECT_EQ(i, statistics_proxy_->GetStats().frames_encoded);
371   }
372 }
373 
TEST_F(SendStatisticsProxyTest,OnSendEncodedImageIncreasesQpSum)374 TEST_F(SendStatisticsProxyTest, OnSendEncodedImageIncreasesQpSum) {
375   EncodedImage encoded_image;
376   CodecSpecificInfo codec_info;
377   auto ssrc = config_.rtp.ssrcs[0];
378   EXPECT_EQ(absl::nullopt,
379             statistics_proxy_->GetStats().substreams[ssrc].qp_sum);
380   encoded_image.qp_ = 3;
381   statistics_proxy_->OnSendEncodedImage(encoded_image, &codec_info);
382   EXPECT_EQ(3u, statistics_proxy_->GetStats().substreams[ssrc].qp_sum);
383   encoded_image.qp_ = 127;
384   statistics_proxy_->OnSendEncodedImage(encoded_image, &codec_info);
385   EXPECT_EQ(130u, statistics_proxy_->GetStats().substreams[ssrc].qp_sum);
386 }
387 
TEST_F(SendStatisticsProxyTest,OnSendEncodedImageWithoutQpQpSumWontExist)388 TEST_F(SendStatisticsProxyTest, OnSendEncodedImageWithoutQpQpSumWontExist) {
389   EncodedImage encoded_image;
390   CodecSpecificInfo codec_info;
391   auto ssrc = config_.rtp.ssrcs[0];
392   encoded_image.qp_ = -1;
393   EXPECT_EQ(absl::nullopt,
394             statistics_proxy_->GetStats().substreams[ssrc].qp_sum);
395   statistics_proxy_->OnSendEncodedImage(encoded_image, &codec_info);
396   EXPECT_EQ(absl::nullopt,
397             statistics_proxy_->GetStats().substreams[ssrc].qp_sum);
398 }
399 
TEST_F(SendStatisticsProxyTest,TotalEncodedBytesTargetFirstFrame)400 TEST_F(SendStatisticsProxyTest, TotalEncodedBytesTargetFirstFrame) {
401   const uint32_t kTargetBytesPerSecond = 100000;
402   statistics_proxy_->OnSetEncoderTargetRate(kTargetBytesPerSecond * 8);
403   EXPECT_EQ(0u, statistics_proxy_->GetStats().total_encoded_bytes_target);
404 
405   EncodedImage encoded_image;
406   statistics_proxy_->OnSendEncodedImage(encoded_image, nullptr);
407   // On the first frame we don't know the frame rate yet, calculation yields
408   // zero. Our estimate assumes at least 1 FPS, so we expect the frame size to
409   // increment by a full `kTargetBytesPerSecond`.
410   EXPECT_EQ(kTargetBytesPerSecond,
411             statistics_proxy_->GetStats().total_encoded_bytes_target);
412 }
413 
TEST_F(SendStatisticsProxyTest,TotalEncodedBytesTargetIncrementsBasedOnFrameRate)414 TEST_F(SendStatisticsProxyTest,
415        TotalEncodedBytesTargetIncrementsBasedOnFrameRate) {
416   const uint32_t kTargetBytesPerSecond = 100000;
417   const int kInterframeDelayMs = 100;
418 
419   // SendStatisticsProxy uses a RateTracker internally. SendStatisticsProxy uses
420   // `fake_clock_` for testing, but the RateTracker relies on a global clock.
421   // This test relies on rtc::ScopedFakeClock to synchronize these two clocks.
422   // TODO(https://crbug.com/webrtc/10640): When the RateTracker uses a Clock
423   // this test can stop relying on rtc::ScopedFakeClock.
424   rtc::ScopedFakeClock fake_global_clock;
425   fake_global_clock.SetTime(
426       Timestamp::Millis(fake_clock_.TimeInMilliseconds()));
427 
428   statistics_proxy_->OnSetEncoderTargetRate(kTargetBytesPerSecond * 8);
429   EncodedImage encoded_image;
430 
431   // First frame
432   statistics_proxy_->OnSendEncodedImage(encoded_image, nullptr);
433   uint64_t first_total_encoded_bytes_target =
434       statistics_proxy_->GetStats().total_encoded_bytes_target;
435   // Second frame
436   fake_clock_.AdvanceTimeMilliseconds(kInterframeDelayMs);
437   fake_global_clock.SetTime(
438       Timestamp::Millis(fake_clock_.TimeInMilliseconds()));
439   encoded_image.SetTimestamp(encoded_image.Timestamp() +
440                              90 * kInterframeDelayMs);
441   statistics_proxy_->OnSendEncodedImage(encoded_image, nullptr);
442 
443   auto stats = statistics_proxy_->GetStats();
444   // By the time the second frame arrives, one frame has previously arrived
445   // during a `kInterframeDelayMs` interval. The estimated encode frame rate at
446   // the second frame's arrival should be 10 FPS.
447   uint64_t delta_encoded_bytes_target =
448       stats.total_encoded_bytes_target - first_total_encoded_bytes_target;
449   EXPECT_EQ(kTargetBytesPerSecond / 10, delta_encoded_bytes_target);
450 }
451 
TEST_F(SendStatisticsProxyTest,EncodeFrameRateInSubStream)452 TEST_F(SendStatisticsProxyTest, EncodeFrameRateInSubStream) {
453   const int kInterframeDelayMs = 100;
454   const auto ssrc = config_.rtp.ssrcs[0];
455   rtc::ScopedFakeClock fake_global_clock;
456   fake_global_clock.SetTime(
457       Timestamp::Millis(fake_clock_.TimeInMilliseconds()));
458 
459   // First frame
460   EncodedImage encoded_image;
461   statistics_proxy_->OnSendEncodedImage(encoded_image, nullptr);
462   fake_clock_.AdvanceTimeMilliseconds(kInterframeDelayMs);
463   fake_global_clock.SetTime(
464       Timestamp::Millis(fake_clock_.TimeInMilliseconds()));
465   // Second frame
466   encoded_image.SetTimestamp(encoded_image.Timestamp() +
467                              90 * kInterframeDelayMs);
468   statistics_proxy_->OnSendEncodedImage(encoded_image, nullptr);
469   fake_clock_.AdvanceTimeMilliseconds(kInterframeDelayMs);
470   fake_global_clock.SetTime(
471       Timestamp::Millis(fake_clock_.TimeInMilliseconds()));
472 
473   auto stats = statistics_proxy_->GetStats();
474   EXPECT_EQ(stats.substreams[ssrc].encode_frame_rate, 10);
475 }
476 
TEST_F(SendStatisticsProxyTest,EncodeFrameRateInSubStreamsVp8Simulcast)477 TEST_F(SendStatisticsProxyTest, EncodeFrameRateInSubStreamsVp8Simulcast) {
478   const int kInterframeDelayMs = 100;
479   rtc::ScopedFakeClock fake_global_clock;
480   fake_global_clock.SetTime(
481       Timestamp::Millis(fake_clock_.TimeInMilliseconds()));
482   EncodedImage encoded_image;
483   CodecSpecificInfo codec_info;
484   codec_info.codecType = kVideoCodecVP8;
485 
486   for (int i = 0; i < 10; ++i) {
487     encoded_image.SetTimestamp(encoded_image.Timestamp() +
488                                90 * kInterframeDelayMs);
489     encoded_image.SetSpatialIndex(0);
490     statistics_proxy_->OnSendEncodedImage(encoded_image, &codec_info);
491     encoded_image.SetSpatialIndex(1);
492     statistics_proxy_->OnSendEncodedImage(encoded_image, &codec_info);
493     fake_clock_.AdvanceTimeMilliseconds(kInterframeDelayMs);
494     fake_global_clock.SetTime(
495         Timestamp::Millis(fake_clock_.TimeInMilliseconds()));
496   }
497 
498   VideoSendStream::Stats stats = statistics_proxy_->GetStats();
499   EXPECT_EQ(2u, stats.substreams.size());
500   EXPECT_EQ(stats.substreams[config_.rtp.ssrcs[0]].encode_frame_rate, 10);
501   EXPECT_EQ(stats.substreams[config_.rtp.ssrcs[1]].encode_frame_rate, 10);
502 
503   // Stop encoding second stream, expect framerate to be zero.
504   for (int i = 0; i < 10; ++i) {
505     encoded_image.SetTimestamp(encoded_image.Timestamp() +
506                                90 * kInterframeDelayMs);
507     encoded_image.SetSpatialIndex(0);
508     statistics_proxy_->OnSendEncodedImage(encoded_image, &codec_info);
509     fake_clock_.AdvanceTimeMilliseconds(kInterframeDelayMs);
510     fake_global_clock.SetTime(
511         Timestamp::Millis(fake_clock_.TimeInMilliseconds()));
512   }
513 
514   stats = statistics_proxy_->GetStats();
515   EXPECT_EQ(2u, stats.substreams.size());
516   EXPECT_EQ(stats.substreams[config_.rtp.ssrcs[0]].encode_frame_rate, 10);
517   EXPECT_EQ(stats.substreams[config_.rtp.ssrcs[1]].encode_frame_rate, 0);
518 
519   // Start encoding second stream.
520   for (int i = 0; i < 10; ++i) {
521     encoded_image.SetTimestamp(encoded_image.Timestamp() +
522                                90 * kInterframeDelayMs);
523     encoded_image.SetSpatialIndex(0);
524     statistics_proxy_->OnSendEncodedImage(encoded_image, &codec_info);
525     encoded_image.SetSpatialIndex(1);
526     statistics_proxy_->OnSendEncodedImage(encoded_image, &codec_info);
527     fake_clock_.AdvanceTimeMilliseconds(kInterframeDelayMs);
528     fake_global_clock.SetTime(
529         Timestamp::Millis(fake_clock_.TimeInMilliseconds()));
530   }
531 
532   stats = statistics_proxy_->GetStats();
533   EXPECT_EQ(2u, stats.substreams.size());
534   EXPECT_EQ(stats.substreams[config_.rtp.ssrcs[0]].encode_frame_rate, 10);
535   EXPECT_EQ(stats.substreams[config_.rtp.ssrcs[1]].encode_frame_rate, 10);
536 }
537 
TEST_F(SendStatisticsProxyTest,EncodeFrameRateInSubStreamsVp9Svc)538 TEST_F(SendStatisticsProxyTest, EncodeFrameRateInSubStreamsVp9Svc) {
539   const int kInterframeDelayMs = 100;
540   rtc::ScopedFakeClock fake_global_clock;
541   fake_global_clock.SetTime(
542       Timestamp::Millis(fake_clock_.TimeInMilliseconds()));
543   EncodedImage encoded_image;
544   CodecSpecificInfo codec_info;
545   codec_info.codecType = kVideoCodecVP9;
546 
547   for (int i = 0; i < 10; ++i) {
548     encoded_image.SetTimestamp(encoded_image.Timestamp() +
549                                90 * kInterframeDelayMs);
550     encoded_image.SetSpatialIndex(0);
551     codec_info.end_of_picture = false;
552     statistics_proxy_->OnSendEncodedImage(encoded_image, &codec_info);
553     encoded_image.SetSpatialIndex(1);
554     codec_info.end_of_picture = true;
555     statistics_proxy_->OnSendEncodedImage(encoded_image, &codec_info);
556     fake_clock_.AdvanceTimeMilliseconds(kInterframeDelayMs);
557     fake_global_clock.SetTime(
558         Timestamp::Millis(fake_clock_.TimeInMilliseconds()));
559   }
560 
561   VideoSendStream::Stats stats = statistics_proxy_->GetStats();
562   EXPECT_EQ(1u, stats.substreams.size());
563   EXPECT_EQ(stats.substreams[config_.rtp.ssrcs[0]].encode_frame_rate, 10);
564 }
565 
TEST_F(SendStatisticsProxyTest,GetCpuAdaptationStats)566 TEST_F(SendStatisticsProxyTest, GetCpuAdaptationStats) {
567   VideoAdaptationCounters cpu_counts;
568   VideoAdaptationCounters quality_counts;
569   EXPECT_FALSE(statistics_proxy_->GetStats().cpu_limited_framerate);
570   EXPECT_FALSE(statistics_proxy_->GetStats().cpu_limited_resolution);
571   cpu_counts.fps_adaptations = 1;
572   cpu_counts.resolution_adaptations = 0;
573   statistics_proxy_->UpdateAdaptationSettings(kScalingEnabled, kScalingEnabled);
574   statistics_proxy_->OnAdaptationChanged(VideoAdaptationReason::kCpu,
575                                          cpu_counts, quality_counts);
576   EXPECT_TRUE(statistics_proxy_->GetStats().cpu_limited_framerate);
577   EXPECT_FALSE(statistics_proxy_->GetStats().cpu_limited_resolution);
578   cpu_counts.fps_adaptations = 0;
579   cpu_counts.resolution_adaptations = 1;
580   statistics_proxy_->OnAdaptationChanged(VideoAdaptationReason::kCpu,
581                                          cpu_counts, quality_counts);
582   EXPECT_FALSE(statistics_proxy_->GetStats().cpu_limited_framerate);
583   EXPECT_TRUE(statistics_proxy_->GetStats().cpu_limited_resolution);
584   cpu_counts.fps_adaptations = 1;
585   statistics_proxy_->UpdateAdaptationSettings(kResolutionScalingDisabled,
586                                               kResolutionScalingDisabled);
587   statistics_proxy_->OnAdaptationChanged(VideoAdaptationReason::kCpu,
588                                          cpu_counts, quality_counts);
589   EXPECT_TRUE(statistics_proxy_->GetStats().cpu_limited_framerate);
590   EXPECT_FALSE(statistics_proxy_->GetStats().cpu_limited_resolution);
591   statistics_proxy_->UpdateAdaptationSettings(kScalingDisabled,
592                                               kScalingDisabled);
593   statistics_proxy_->OnAdaptationChanged(VideoAdaptationReason::kCpu,
594                                          cpu_counts, quality_counts);
595   EXPECT_FALSE(statistics_proxy_->GetStats().cpu_limited_framerate);
596   EXPECT_FALSE(statistics_proxy_->GetStats().cpu_limited_resolution);
597 }
598 
TEST_F(SendStatisticsProxyTest,GetQualityAdaptationStats)599 TEST_F(SendStatisticsProxyTest, GetQualityAdaptationStats) {
600   VideoAdaptationCounters cpu_counts;
601   VideoAdaptationCounters quality_counts;
602   EXPECT_FALSE(statistics_proxy_->GetStats().bw_limited_framerate);
603   EXPECT_FALSE(statistics_proxy_->GetStats().bw_limited_resolution);
604   quality_counts.fps_adaptations = 1;
605   quality_counts.resolution_adaptations = 0;
606   statistics_proxy_->UpdateAdaptationSettings(kScalingEnabled, kScalingEnabled);
607   statistics_proxy_->OnAdaptationChanged(VideoAdaptationReason::kQuality,
608                                          cpu_counts, quality_counts);
609   EXPECT_TRUE(statistics_proxy_->GetStats().bw_limited_framerate);
610   EXPECT_FALSE(statistics_proxy_->GetStats().bw_limited_resolution);
611   quality_counts.fps_adaptations = 0;
612   quality_counts.resolution_adaptations = 1;
613   statistics_proxy_->OnAdaptationChanged(VideoAdaptationReason::kQuality,
614                                          cpu_counts, quality_counts);
615   EXPECT_FALSE(statistics_proxy_->GetStats().bw_limited_framerate);
616   EXPECT_TRUE(statistics_proxy_->GetStats().bw_limited_resolution);
617   quality_counts.fps_adaptations = 1;
618   statistics_proxy_->UpdateAdaptationSettings(kResolutionScalingDisabled,
619                                               kResolutionScalingDisabled);
620   statistics_proxy_->OnAdaptationChanged(VideoAdaptationReason::kQuality,
621                                          cpu_counts, quality_counts);
622   EXPECT_TRUE(statistics_proxy_->GetStats().bw_limited_framerate);
623   EXPECT_FALSE(statistics_proxy_->GetStats().bw_limited_resolution);
624   statistics_proxy_->UpdateAdaptationSettings(kScalingDisabled,
625                                               kScalingDisabled);
626   statistics_proxy_->OnAdaptationChanged(VideoAdaptationReason::kQuality,
627                                          cpu_counts, quality_counts);
628   EXPECT_FALSE(statistics_proxy_->GetStats().bw_limited_framerate);
629   EXPECT_FALSE(statistics_proxy_->GetStats().bw_limited_resolution);
630 }
631 
TEST_F(SendStatisticsProxyTest,GetStatsReportsCpuAdaptChanges)632 TEST_F(SendStatisticsProxyTest, GetStatsReportsCpuAdaptChanges) {
633   statistics_proxy_->UpdateAdaptationSettings(kScalingEnabled, kScalingEnabled);
634   VideoAdaptationCounters cpu_counts;
635   VideoAdaptationCounters quality_counts;
636   EXPECT_EQ(0, statistics_proxy_->GetStats().number_of_cpu_adapt_changes);
637 
638   cpu_counts.resolution_adaptations = 1;
639   statistics_proxy_->OnAdaptationChanged(VideoAdaptationReason::kCpu,
640                                          cpu_counts, quality_counts);
641   EXPECT_FALSE(statistics_proxy_->GetStats().cpu_limited_framerate);
642   EXPECT_TRUE(statistics_proxy_->GetStats().cpu_limited_resolution);
643   EXPECT_EQ(1, statistics_proxy_->GetStats().number_of_cpu_adapt_changes);
644 
645   cpu_counts.resolution_adaptations = 2;
646   statistics_proxy_->OnAdaptationChanged(VideoAdaptationReason::kCpu,
647                                          cpu_counts, quality_counts);
648   EXPECT_FALSE(statistics_proxy_->GetStats().cpu_limited_framerate);
649   EXPECT_TRUE(statistics_proxy_->GetStats().cpu_limited_resolution);
650   EXPECT_EQ(2, statistics_proxy_->GetStats().number_of_cpu_adapt_changes);
651   EXPECT_EQ(0, statistics_proxy_->GetStats().number_of_quality_adapt_changes);
652 }
653 
TEST_F(SendStatisticsProxyTest,GetStatsReportsQualityAdaptChanges)654 TEST_F(SendStatisticsProxyTest, GetStatsReportsQualityAdaptChanges) {
655   VideoAdaptationCounters cpu_counts;
656   VideoAdaptationCounters quality_counts;
657   statistics_proxy_->UpdateAdaptationSettings(kScalingEnabled, kScalingEnabled);
658   EXPECT_EQ(0, statistics_proxy_->GetStats().number_of_quality_adapt_changes);
659 
660   quality_counts.fps_adaptations = 1;
661   statistics_proxy_->OnAdaptationChanged(VideoAdaptationReason::kQuality,
662                                          cpu_counts, quality_counts);
663   EXPECT_TRUE(statistics_proxy_->GetStats().bw_limited_framerate);
664   EXPECT_FALSE(statistics_proxy_->GetStats().bw_limited_resolution);
665   EXPECT_EQ(1, statistics_proxy_->GetStats().number_of_quality_adapt_changes);
666 
667   quality_counts.fps_adaptations = 0;
668   statistics_proxy_->OnAdaptationChanged(VideoAdaptationReason::kQuality,
669                                          cpu_counts, quality_counts);
670   EXPECT_FALSE(statistics_proxy_->GetStats().bw_limited_framerate);
671   EXPECT_FALSE(statistics_proxy_->GetStats().bw_limited_resolution);
672   EXPECT_EQ(2, statistics_proxy_->GetStats().number_of_quality_adapt_changes);
673   EXPECT_EQ(0, statistics_proxy_->GetStats().number_of_cpu_adapt_changes);
674 }
675 
TEST_F(SendStatisticsProxyTest,TestAdaptationStatisticsMasking)676 TEST_F(SendStatisticsProxyTest, TestAdaptationStatisticsMasking) {
677   VideoAdaptationCounters cpu_counts;
678   VideoAdaptationCounters quality_counts;
679   statistics_proxy_->UpdateAdaptationSettings(kScalingEnabled, kScalingEnabled);
680   EXPECT_EQ(0, statistics_proxy_->GetStats().number_of_quality_adapt_changes);
681   EXPECT_EQ(0, statistics_proxy_->GetStats().number_of_cpu_adapt_changes);
682 
683   quality_counts.resolution_adaptations = 1;
684   statistics_proxy_->OnAdaptationChanged(VideoAdaptationReason::kQuality,
685                                          cpu_counts, quality_counts);
686   quality_counts.fps_adaptations = 1;
687   statistics_proxy_->OnAdaptationChanged(VideoAdaptationReason::kQuality,
688                                          cpu_counts, quality_counts);
689   cpu_counts.resolution_adaptations = 1;
690   statistics_proxy_->OnAdaptationChanged(VideoAdaptationReason::kCpu,
691                                          cpu_counts, quality_counts);
692   cpu_counts.fps_adaptations = 1;
693   statistics_proxy_->OnAdaptationChanged(VideoAdaptationReason::kCpu,
694                                          cpu_counts, quality_counts);
695   // We have 1 fps and resolution reduction for both cpu and quality
696   EXPECT_TRUE(statistics_proxy_->GetStats().bw_limited_framerate);
697   EXPECT_TRUE(statistics_proxy_->GetStats().bw_limited_resolution);
698   EXPECT_TRUE(statistics_proxy_->GetStats().cpu_limited_framerate);
699   EXPECT_TRUE(statistics_proxy_->GetStats().cpu_limited_resolution);
700   EXPECT_EQ(2, statistics_proxy_->GetStats().number_of_quality_adapt_changes);
701   EXPECT_EQ(2, statistics_proxy_->GetStats().number_of_cpu_adapt_changes);
702 
703   // Disable quality scaling. Expect quality scaling not limited.
704   statistics_proxy_->UpdateAdaptationSettings(kScalingEnabled,
705                                               kScalingDisabled);
706   EXPECT_FALSE(statistics_proxy_->GetStats().bw_limited_framerate);
707   EXPECT_FALSE(statistics_proxy_->GetStats().bw_limited_resolution);
708   EXPECT_TRUE(statistics_proxy_->GetStats().cpu_limited_framerate);
709   EXPECT_TRUE(statistics_proxy_->GetStats().cpu_limited_resolution);
710   EXPECT_EQ(2, statistics_proxy_->GetStats().number_of_quality_adapt_changes);
711   EXPECT_EQ(2, statistics_proxy_->GetStats().number_of_cpu_adapt_changes);
712 
713   // Disable framerate scaling.
714   statistics_proxy_->UpdateAdaptationSettings(kFramerateScalingDisabled,
715                                               kFramerateScalingDisabled);
716   EXPECT_FALSE(statistics_proxy_->GetStats().bw_limited_framerate);
717   EXPECT_TRUE(statistics_proxy_->GetStats().bw_limited_resolution);
718   EXPECT_FALSE(statistics_proxy_->GetStats().cpu_limited_framerate);
719   EXPECT_TRUE(statistics_proxy_->GetStats().cpu_limited_resolution);
720   EXPECT_EQ(2, statistics_proxy_->GetStats().number_of_quality_adapt_changes);
721   EXPECT_EQ(2, statistics_proxy_->GetStats().number_of_cpu_adapt_changes);
722 
723   // Disable resolution scaling.
724   statistics_proxy_->UpdateAdaptationSettings(kResolutionScalingDisabled,
725                                               kResolutionScalingDisabled);
726   EXPECT_TRUE(statistics_proxy_->GetStats().bw_limited_framerate);
727   EXPECT_FALSE(statistics_proxy_->GetStats().bw_limited_resolution);
728   EXPECT_TRUE(statistics_proxy_->GetStats().cpu_limited_framerate);
729   EXPECT_FALSE(statistics_proxy_->GetStats().cpu_limited_resolution);
730   EXPECT_EQ(2, statistics_proxy_->GetStats().number_of_quality_adapt_changes);
731   EXPECT_EQ(2, statistics_proxy_->GetStats().number_of_cpu_adapt_changes);
732 
733   // Enable all
734   statistics_proxy_->UpdateAdaptationSettings(kScalingEnabled, kScalingEnabled);
735   EXPECT_TRUE(statistics_proxy_->GetStats().bw_limited_framerate);
736   EXPECT_TRUE(statistics_proxy_->GetStats().bw_limited_resolution);
737   EXPECT_TRUE(statistics_proxy_->GetStats().cpu_limited_framerate);
738   EXPECT_TRUE(statistics_proxy_->GetStats().cpu_limited_resolution);
739   EXPECT_EQ(2, statistics_proxy_->GetStats().number_of_quality_adapt_changes);
740   EXPECT_EQ(2, statistics_proxy_->GetStats().number_of_cpu_adapt_changes);
741 }
742 
TEST_F(SendStatisticsProxyTest,AdaptChangesNotReported_AdaptationNotEnabled)743 TEST_F(SendStatisticsProxyTest, AdaptChangesNotReported_AdaptationNotEnabled) {
744   // First RTP packet sent.
745   UpdateDataCounters(kFirstSsrc);
746   // Min runtime has passed.
747   fake_clock_.AdvanceTimeMilliseconds(metrics::kMinRunTimeInSeconds * 1000);
748   statistics_proxy_.reset();
749   EXPECT_METRIC_EQ(
750       0, metrics::NumSamples("WebRTC.Video.AdaptChangesPerMinute.Cpu"));
751   EXPECT_METRIC_EQ(
752       0, metrics::NumSamples("WebRTC.Video.AdaptChangesPerMinute.Quality"));
753 }
754 
TEST_F(SendStatisticsProxyTest,AdaptChangesNotReported_MinRuntimeNotPassed)755 TEST_F(SendStatisticsProxyTest, AdaptChangesNotReported_MinRuntimeNotPassed) {
756   // First RTP packet sent.
757   UpdateDataCounters(kFirstSsrc);
758   // Enable adaptation.
759   statistics_proxy_->UpdateAdaptationSettings(kScalingEnabled, kScalingEnabled);
760   // Min runtime has not passed.
761   fake_clock_.AdvanceTimeMilliseconds(metrics::kMinRunTimeInSeconds * 1000 - 1);
762   statistics_proxy_.reset();
763   EXPECT_METRIC_EQ(
764       0, metrics::NumSamples("WebRTC.Video.AdaptChangesPerMinute.Cpu"));
765   EXPECT_METRIC_EQ(
766       0, metrics::NumSamples("WebRTC.Video.AdaptChangesPerMinute.Quality"));
767 }
768 
TEST_F(SendStatisticsProxyTest,ZeroAdaptChangesReported)769 TEST_F(SendStatisticsProxyTest, ZeroAdaptChangesReported) {
770   // First RTP packet sent.
771   UpdateDataCounters(kFirstSsrc);
772   // Enable adaptation.
773   statistics_proxy_->UpdateAdaptationSettings(kScalingEnabled, kScalingEnabled);
774   // Min runtime has passed.
775   fake_clock_.AdvanceTimeMilliseconds(metrics::kMinRunTimeInSeconds * 1000);
776   statistics_proxy_.reset();
777   EXPECT_METRIC_EQ(
778       1, metrics::NumSamples("WebRTC.Video.AdaptChangesPerMinute.Cpu"));
779   EXPECT_METRIC_EQ(
780       1, metrics::NumEvents("WebRTC.Video.AdaptChangesPerMinute.Cpu", 0));
781   EXPECT_METRIC_EQ(
782       1, metrics::NumSamples("WebRTC.Video.AdaptChangesPerMinute.Quality"));
783   EXPECT_METRIC_EQ(
784       1, metrics::NumEvents("WebRTC.Video.AdaptChangesPerMinute.Quality", 0));
785 }
786 
TEST_F(SendStatisticsProxyTest,CpuAdaptChangesReported)787 TEST_F(SendStatisticsProxyTest, CpuAdaptChangesReported) {
788   // First RTP packet sent.
789   UpdateDataCounters(kFirstSsrc);
790   // Enable adaptation.
791   VideoAdaptationCounters cpu_counts;
792   VideoAdaptationCounters quality_counts;
793   statistics_proxy_->UpdateAdaptationSettings(kScalingEnabled, kScalingEnabled);
794   // Adapt changes: 1, elapsed time: 10 sec => 6 per minute.
795   statistics_proxy_->OnAdaptationChanged(VideoAdaptationReason::kCpu,
796                                          cpu_counts, quality_counts);
797   fake_clock_.AdvanceTimeMilliseconds(10000);
798   statistics_proxy_.reset();
799   EXPECT_METRIC_EQ(
800       1, metrics::NumSamples("WebRTC.Video.AdaptChangesPerMinute.Cpu"));
801   EXPECT_METRIC_EQ(
802       1, metrics::NumEvents("WebRTC.Video.AdaptChangesPerMinute.Cpu", 6));
803 }
804 
TEST_F(SendStatisticsProxyTest,ExcludesInitialQualityAdaptDownChange)805 TEST_F(SendStatisticsProxyTest, ExcludesInitialQualityAdaptDownChange) {
806   // First RTP packet sent.
807   UpdateDataCounters(kFirstSsrc);
808   // Enable adaptation.
809   VideoAdaptationCounters cpu_counts;
810   VideoAdaptationCounters quality_counts;
811   statistics_proxy_->UpdateAdaptationSettings(kScalingEnabled, kScalingEnabled);
812   // Adapt changes: 1 (1 initial) = 0, elapsed time: 10 sec => 0 per minute.
813   statistics_proxy_->OnAdaptationChanged(VideoAdaptationReason::kQuality,
814                                          cpu_counts, quality_counts);
815   statistics_proxy_->OnInitialQualityResolutionAdaptDown();
816   fake_clock_.AdvanceTimeMilliseconds(10000);
817   statistics_proxy_.reset();
818   EXPECT_METRIC_EQ(
819       1, metrics::NumSamples("WebRTC.Video.AdaptChangesPerMinute.Quality"));
820   EXPECT_METRIC_EQ(
821       1, metrics::NumEvents("WebRTC.Video.AdaptChangesPerMinute.Quality", 0));
822 }
823 
TEST_F(SendStatisticsProxyTest,ExcludesInitialQualityAdaptDownChanges)824 TEST_F(SendStatisticsProxyTest, ExcludesInitialQualityAdaptDownChanges) {
825   // First RTP packet sent.
826   UpdateDataCounters(kFirstSsrc);
827   // Enable adaptation.
828   VideoAdaptationCounters cpu_counts;
829   VideoAdaptationCounters quality_counts;
830   statistics_proxy_->UpdateAdaptationSettings(kScalingEnabled, kScalingEnabled);
831   // Adapt changes: 3 (2 initial) = 1, elapsed time: 10 sec => 6 per minute.
832   quality_counts.resolution_adaptations = 1;
833   statistics_proxy_->OnAdaptationChanged(VideoAdaptationReason::kQuality,
834                                          cpu_counts, quality_counts);
835   statistics_proxy_->OnInitialQualityResolutionAdaptDown();
836   quality_counts.resolution_adaptations = 2;
837   statistics_proxy_->OnAdaptationChanged(VideoAdaptationReason::kQuality,
838                                          cpu_counts, quality_counts);
839   statistics_proxy_->OnInitialQualityResolutionAdaptDown();
840   quality_counts.resolution_adaptations = 3;
841   statistics_proxy_->OnAdaptationChanged(VideoAdaptationReason::kQuality,
842                                          cpu_counts, quality_counts);
843   fake_clock_.AdvanceTimeMilliseconds(10000);
844   statistics_proxy_.reset();
845   EXPECT_METRIC_EQ(
846       1, metrics::NumSamples("WebRTC.Video.AdaptChangesPerMinute.Quality"));
847   EXPECT_METRIC_EQ(
848       1, metrics::NumEvents("WebRTC.Video.AdaptChangesPerMinute.Quality", 6));
849 }
850 
TEST_F(SendStatisticsProxyTest,InitialQualityAdaptChangesNotExcludedOnError)851 TEST_F(SendStatisticsProxyTest, InitialQualityAdaptChangesNotExcludedOnError) {
852   // First RTP packet sent.
853   UpdateDataCounters(kFirstSsrc);
854   // Enable adaptation.
855   VideoAdaptationCounters cpu_counts;
856   VideoAdaptationCounters quality_counts;
857   statistics_proxy_->UpdateAdaptationSettings(kScalingEnabled, kScalingEnabled);
858   // Adapt changes: 1 (2 initial) = 1, elapsed time: 10 sec => 6 per minute.
859   statistics_proxy_->OnAdaptationChanged(VideoAdaptationReason::kQuality,
860                                          cpu_counts, quality_counts);
861   statistics_proxy_->OnInitialQualityResolutionAdaptDown();
862   statistics_proxy_->OnInitialQualityResolutionAdaptDown();
863   fake_clock_.AdvanceTimeMilliseconds(10000);
864   statistics_proxy_.reset();
865   EXPECT_METRIC_EQ(
866       1, metrics::NumSamples("WebRTC.Video.AdaptChangesPerMinute.Quality"));
867   EXPECT_METRIC_EQ(
868       1, metrics::NumEvents("WebRTC.Video.AdaptChangesPerMinute.Quality", 6));
869 }
870 
TEST_F(SendStatisticsProxyTest,ExcludesInitialQualityAdaptDownAndUpChanges)871 TEST_F(SendStatisticsProxyTest, ExcludesInitialQualityAdaptDownAndUpChanges) {
872   // First RTP packet sent.
873   UpdateDataCounters(kFirstSsrc);
874   // Enable adaptation.
875   statistics_proxy_->UpdateAdaptationSettings(kScalingEnabled, kScalingEnabled);
876   VideoAdaptationCounters cpu_counts;
877   VideoAdaptationCounters quality_counts;
878   statistics_proxy_->ClearAdaptationStats();
879   // Adapt changes: 8 (4 initial) = 4, elapsed time: 10 sec => 24 per minute.
880   quality_counts.resolution_adaptations = 1;
881   statistics_proxy_->OnAdaptationChanged(VideoAdaptationReason::kQuality,
882                                          cpu_counts, quality_counts);
883   statistics_proxy_->OnInitialQualityResolutionAdaptDown();
884   quality_counts.resolution_adaptations = 2;
885   statistics_proxy_->OnAdaptationChanged(VideoAdaptationReason::kQuality,
886                                          cpu_counts, quality_counts);
887   statistics_proxy_->OnInitialQualityResolutionAdaptDown();
888   quality_counts.resolution_adaptations = 3;
889   statistics_proxy_->OnAdaptationChanged(VideoAdaptationReason::kQuality,
890                                          cpu_counts, quality_counts);
891   quality_counts.fps_adaptations = 1;
892   statistics_proxy_->OnAdaptationChanged(VideoAdaptationReason::kQuality,
893                                          cpu_counts, quality_counts);
894   quality_counts.fps_adaptations = 0;
895   statistics_proxy_->OnAdaptationChanged(VideoAdaptationReason::kQuality,
896                                          cpu_counts, quality_counts);
897   quality_counts.resolution_adaptations = 2;  // Initial resolution up.
898   statistics_proxy_->OnAdaptationChanged(VideoAdaptationReason::kQuality,
899                                          cpu_counts, quality_counts);
900   quality_counts.resolution_adaptations = 1;  // Initial resolution up.
901   statistics_proxy_->OnAdaptationChanged(VideoAdaptationReason::kQuality,
902                                          cpu_counts, quality_counts);
903   quality_counts.resolution_adaptations = 0;
904   statistics_proxy_->OnAdaptationChanged(VideoAdaptationReason::kQuality,
905                                          cpu_counts, quality_counts);
906 
907   fake_clock_.AdvanceTimeMilliseconds(10000);
908   statistics_proxy_.reset();
909   EXPECT_METRIC_EQ(
910       1, metrics::NumSamples("WebRTC.Video.AdaptChangesPerMinute.Quality"));
911   EXPECT_METRIC_EQ(
912       1, metrics::NumEvents("WebRTC.Video.AdaptChangesPerMinute.Quality", 24));
913 }
914 
TEST_F(SendStatisticsProxyTest,AdaptChangesStatsExcludesDisabledTime)915 TEST_F(SendStatisticsProxyTest, AdaptChangesStatsExcludesDisabledTime) {
916   // First RTP packet sent.
917   UpdateDataCounters(kFirstSsrc);
918 
919   // Disable quality adaptation.
920   VideoAdaptationCounters cpu_counts;
921   VideoAdaptationCounters quality_counts;
922   statistics_proxy_->UpdateAdaptationSettings(kScalingEnabled,
923                                               kScalingDisabled);
924   fake_clock_.AdvanceTimeMilliseconds(10000);
925 
926   // Enable quality adaptation.
927   // Adapt changes: 2, elapsed time: 20 sec.
928   quality_counts.fps_adaptations = 0;
929   statistics_proxy_->UpdateAdaptationSettings(kResolutionScalingDisabled,
930                                               kResolutionScalingDisabled);
931   fake_clock_.AdvanceTimeMilliseconds(5000);
932   statistics_proxy_->UpdateAdaptationSettings(kResolutionScalingDisabled,
933                                               kResolutionScalingDisabled);
934   fake_clock_.AdvanceTimeMilliseconds(9000);
935   statistics_proxy_->OnAdaptationChanged(VideoAdaptationReason::kQuality,
936                                          cpu_counts, quality_counts);
937   fake_clock_.AdvanceTimeMilliseconds(6000);
938   statistics_proxy_->OnAdaptationChanged(VideoAdaptationReason::kQuality,
939                                          cpu_counts, quality_counts);
940 
941   // Disable quality adaptation.
942   statistics_proxy_->UpdateAdaptationSettings(kScalingDisabled,
943                                               kScalingDisabled);
944   fake_clock_.AdvanceTimeMilliseconds(30000);
945 
946   // Enable quality adaptation.
947   // Adapt changes: 1, elapsed time: 10 sec.
948   quality_counts.resolution_adaptations = 0;
949   statistics_proxy_->UpdateAdaptationSettings(kFramerateScalingDisabled,
950                                               kFramerateScalingDisabled);
951   statistics_proxy_->OnAdaptationChanged(VideoAdaptationReason::kQuality,
952                                          cpu_counts, quality_counts);
953   fake_clock_.AdvanceTimeMilliseconds(10000);
954 
955   // Disable quality adaptation.
956   statistics_proxy_->UpdateAdaptationSettings(kScalingDisabled,
957                                               kScalingDisabled);
958   fake_clock_.AdvanceTimeMilliseconds(5000);
959   statistics_proxy_->UpdateAdaptationSettings(kScalingDisabled,
960                                               kScalingDisabled);
961   fake_clock_.AdvanceTimeMilliseconds(20000);
962 
963   // Adapt changes: 3, elapsed time: 30 sec => 6 per minute.
964   statistics_proxy_.reset();
965   EXPECT_METRIC_EQ(
966       1, metrics::NumSamples("WebRTC.Video.AdaptChangesPerMinute.Quality"));
967   EXPECT_METRIC_EQ(
968       1, metrics::NumEvents("WebRTC.Video.AdaptChangesPerMinute.Quality", 6));
969 }
970 
TEST_F(SendStatisticsProxyTest,AdaptChangesNotReported_ScalingNotEnabledVideoResumed)971 TEST_F(SendStatisticsProxyTest,
972        AdaptChangesNotReported_ScalingNotEnabledVideoResumed) {
973   // First RTP packet sent.
974   UpdateDataCounters(kFirstSsrc);
975 
976   // Suspend and resume video.
977   statistics_proxy_->OnSuspendChange(true);
978   fake_clock_.AdvanceTimeMilliseconds(5000);
979   statistics_proxy_->OnSuspendChange(false);
980 
981   // Min runtime has passed but scaling not enabled.
982   fake_clock_.AdvanceTimeMilliseconds(metrics::kMinRunTimeInSeconds * 1000);
983   statistics_proxy_.reset();
984   EXPECT_METRIC_EQ(
985       0, metrics::NumSamples("WebRTC.Video.AdaptChangesPerMinute.Cpu"));
986   EXPECT_METRIC_EQ(
987       0, metrics::NumSamples("WebRTC.Video.AdaptChangesPerMinute.Quality"));
988 }
989 
TEST_F(SendStatisticsProxyTest,QualityAdaptChangesStatsExcludesSuspendedTime)990 TEST_F(SendStatisticsProxyTest, QualityAdaptChangesStatsExcludesSuspendedTime) {
991   // First RTP packet sent.
992   UpdateDataCounters(kFirstSsrc);
993 
994   // Enable adaptation.
995   VideoAdaptationCounters cpu_counts;
996   VideoAdaptationCounters quality_counts;
997   // Adapt changes: 2, elapsed time: 20 sec.
998   statistics_proxy_->UpdateAdaptationSettings(kScalingEnabled, kScalingEnabled);
999   fake_clock_.AdvanceTimeMilliseconds(20000);
1000   statistics_proxy_->OnAdaptationChanged(VideoAdaptationReason::kQuality,
1001                                          cpu_counts, quality_counts);
1002   statistics_proxy_->OnAdaptationChanged(VideoAdaptationReason::kQuality,
1003                                          cpu_counts, quality_counts);
1004 
1005   // Suspend and resume video.
1006   statistics_proxy_->OnSuspendChange(true);
1007   fake_clock_.AdvanceTimeMilliseconds(30000);
1008   statistics_proxy_->OnSuspendChange(false);
1009 
1010   // Adapt changes: 1, elapsed time: 10 sec.
1011   statistics_proxy_->OnAdaptationChanged(VideoAdaptationReason::kQuality,
1012                                          cpu_counts, quality_counts);
1013   fake_clock_.AdvanceTimeMilliseconds(10000);
1014 
1015   // Adapt changes: 3, elapsed time: 30 sec => 6 per minute.
1016   statistics_proxy_.reset();
1017   EXPECT_METRIC_EQ(
1018       1, metrics::NumSamples("WebRTC.Video.AdaptChangesPerMinute.Quality"));
1019   EXPECT_METRIC_EQ(
1020       1, metrics::NumEvents("WebRTC.Video.AdaptChangesPerMinute.Quality", 6));
1021 }
1022 
TEST_F(SendStatisticsProxyTest,CpuAdaptChangesStatsExcludesSuspendedTime)1023 TEST_F(SendStatisticsProxyTest, CpuAdaptChangesStatsExcludesSuspendedTime) {
1024   // First RTP packet sent.
1025   UpdateDataCounters(kFirstSsrc);
1026 
1027   // Video not suspended.
1028   statistics_proxy_->OnSuspendChange(false);
1029   fake_clock_.AdvanceTimeMilliseconds(30000);
1030 
1031   // Enable adaptation.
1032   VideoAdaptationCounters cpu_counts;
1033   VideoAdaptationCounters quality_counts;
1034   // Adapt changes: 1, elapsed time: 20 sec.
1035   statistics_proxy_->UpdateAdaptationSettings(kScalingEnabled, kScalingEnabled);
1036   fake_clock_.AdvanceTimeMilliseconds(10000);
1037   statistics_proxy_->OnAdaptationChanged(VideoAdaptationReason::kCpu,
1038                                          cpu_counts, quality_counts);
1039 
1040   // Video not suspended, stats time already started.
1041   statistics_proxy_->OnSuspendChange(false);
1042   fake_clock_.AdvanceTimeMilliseconds(10000);
1043 
1044   // Disable adaptation.
1045   statistics_proxy_->UpdateAdaptationSettings(kScalingDisabled,
1046                                               kScalingDisabled);
1047   fake_clock_.AdvanceTimeMilliseconds(30000);
1048 
1049   // Suspend and resume video, stats time not started when scaling not enabled.
1050   statistics_proxy_->OnSuspendChange(true);
1051   fake_clock_.AdvanceTimeMilliseconds(30000);
1052   statistics_proxy_->OnSuspendChange(false);
1053   fake_clock_.AdvanceTimeMilliseconds(30000);
1054 
1055   // Enable adaptation.
1056   // Adapt changes: 1, elapsed time: 10 sec.
1057   cpu_counts.fps_adaptations = 0;
1058   cpu_counts.resolution_adaptations = 0;
1059   statistics_proxy_->UpdateAdaptationSettings(kScalingEnabled, kScalingEnabled);
1060   fake_clock_.AdvanceTimeMilliseconds(10000);
1061   statistics_proxy_->OnAdaptationChanged(VideoAdaptationReason::kCpu,
1062                                          cpu_counts, quality_counts);
1063 
1064   // Adapt changes: 2, elapsed time: 30 sec => 4 per minute.
1065   statistics_proxy_.reset();
1066   EXPECT_METRIC_EQ(
1067       1, metrics::NumSamples("WebRTC.Video.AdaptChangesPerMinute.Cpu"));
1068   EXPECT_METRIC_EQ(
1069       1, metrics::NumEvents("WebRTC.Video.AdaptChangesPerMinute.Cpu", 4));
1070 }
1071 
TEST_F(SendStatisticsProxyTest,AdaptChangesStatsNotStartedIfVideoSuspended)1072 TEST_F(SendStatisticsProxyTest, AdaptChangesStatsNotStartedIfVideoSuspended) {
1073   // First RTP packet sent.
1074   UpdateDataCounters(kFirstSsrc);
1075 
1076   // Video suspended.
1077   statistics_proxy_->OnSuspendChange(true);
1078 
1079   // Enable adaptation, stats time not started when suspended.
1080   VideoAdaptationCounters cpu_counts;
1081   VideoAdaptationCounters quality_counts;
1082   statistics_proxy_->UpdateAdaptationSettings(kScalingEnabled, kScalingEnabled);
1083   fake_clock_.AdvanceTimeMilliseconds(10000);
1084 
1085   // Resume video, stats time started.
1086   // Adapt changes: 1, elapsed time: 10 sec.
1087   statistics_proxy_->OnSuspendChange(false);
1088   fake_clock_.AdvanceTimeMilliseconds(10000);
1089   statistics_proxy_->OnAdaptationChanged(VideoAdaptationReason::kCpu,
1090                                          cpu_counts, quality_counts);
1091 
1092   // Adapt changes: 1, elapsed time: 10 sec => 6 per minute.
1093   statistics_proxy_.reset();
1094   EXPECT_METRIC_EQ(
1095       1, metrics::NumSamples("WebRTC.Video.AdaptChangesPerMinute.Cpu"));
1096   EXPECT_METRIC_EQ(
1097       1, metrics::NumEvents("WebRTC.Video.AdaptChangesPerMinute.Cpu", 6));
1098 }
1099 
TEST_F(SendStatisticsProxyTest,AdaptChangesStatsRestartsOnFirstSentPacket)1100 TEST_F(SendStatisticsProxyTest, AdaptChangesStatsRestartsOnFirstSentPacket) {
1101   // Send first packet, adaptation enabled.
1102   // Elapsed time before first packet is sent should be excluded.
1103   VideoAdaptationCounters cpu_counts;
1104   VideoAdaptationCounters quality_counts;
1105   statistics_proxy_->UpdateAdaptationSettings(kScalingEnabled, kScalingEnabled);
1106   fake_clock_.AdvanceTimeMilliseconds(10000);
1107   UpdateDataCounters(kFirstSsrc);
1108 
1109   // Adapt changes: 1, elapsed time: 10 sec.
1110   fake_clock_.AdvanceTimeMilliseconds(10000);
1111   statistics_proxy_->OnAdaptationChanged(VideoAdaptationReason::kQuality,
1112                                          cpu_counts, quality_counts);
1113   UpdateDataCounters(kFirstSsrc);
1114 
1115   // Adapt changes: 1, elapsed time: 10 sec => 6 per minute.
1116   statistics_proxy_.reset();
1117   EXPECT_METRIC_EQ(
1118       1, metrics::NumSamples("WebRTC.Video.AdaptChangesPerMinute.Quality"));
1119   EXPECT_METRIC_EQ(
1120       1, metrics::NumEvents("WebRTC.Video.AdaptChangesPerMinute.Quality", 6));
1121 }
1122 
TEST_F(SendStatisticsProxyTest,AdaptChangesStatsStartedAfterFirstSentPacket)1123 TEST_F(SendStatisticsProxyTest, AdaptChangesStatsStartedAfterFirstSentPacket) {
1124   // Enable and disable adaptation.
1125   VideoAdaptationCounters cpu_counts;
1126   VideoAdaptationCounters quality_counts;
1127   statistics_proxy_->UpdateAdaptationSettings(kScalingEnabled, kScalingEnabled);
1128   fake_clock_.AdvanceTimeMilliseconds(60000);
1129   statistics_proxy_->UpdateAdaptationSettings(kScalingDisabled,
1130                                               kScalingDisabled);
1131 
1132   // Send first packet, scaling disabled.
1133   // Elapsed time before first packet is sent should be excluded.
1134   UpdateDataCounters(kFirstSsrc);
1135   fake_clock_.AdvanceTimeMilliseconds(60000);
1136 
1137   // Enable adaptation.
1138   cpu_counts.resolution_adaptations = 0;
1139   statistics_proxy_->UpdateAdaptationSettings(kFramerateScalingDisabled,
1140                                               kScalingDisabled);
1141   fake_clock_.AdvanceTimeMilliseconds(10000);
1142   UpdateDataCounters(kFirstSsrc);
1143 
1144   // Adapt changes: 1, elapsed time: 20 sec.
1145   fake_clock_.AdvanceTimeMilliseconds(10000);
1146   statistics_proxy_->OnAdaptationChanged(VideoAdaptationReason::kCpu,
1147                                          cpu_counts, quality_counts);
1148 
1149   // Adapt changes: 1, elapsed time: 20 sec => 3 per minute.
1150   statistics_proxy_.reset();
1151   EXPECT_METRIC_EQ(
1152       1, metrics::NumSamples("WebRTC.Video.AdaptChangesPerMinute.Cpu"));
1153   EXPECT_METRIC_EQ(
1154       1, metrics::NumEvents("WebRTC.Video.AdaptChangesPerMinute.Cpu", 3));
1155 }
1156 
TEST_F(SendStatisticsProxyTest,AdaptChangesReportedAfterContentSwitch)1157 TEST_F(SendStatisticsProxyTest, AdaptChangesReportedAfterContentSwitch) {
1158   // First RTP packet sent, cpu adaptation enabled.
1159   UpdateDataCounters(kFirstSsrc);
1160   VideoAdaptationCounters cpu_counts;
1161   VideoAdaptationCounters quality_counts;
1162   statistics_proxy_->UpdateAdaptationSettings(kScalingEnabled,
1163                                               kScalingDisabled);
1164 
1165   // Adapt changes: 2, elapsed time: 15 sec => 8 per minute.
1166   statistics_proxy_->OnAdaptationChanged(VideoAdaptationReason::kCpu,
1167                                          cpu_counts, quality_counts);
1168   fake_clock_.AdvanceTimeMilliseconds(6000);
1169   statistics_proxy_->OnAdaptationChanged(VideoAdaptationReason::kCpu,
1170                                          cpu_counts, quality_counts);
1171   fake_clock_.AdvanceTimeMilliseconds(9000);
1172 
1173   // Switch content type, real-time stats should be updated.
1174   VideoEncoderConfig config;
1175   config.content_type = VideoEncoderConfig::ContentType::kScreen;
1176   statistics_proxy_->OnEncoderReconfigured(config, {});
1177   EXPECT_METRIC_EQ(
1178       1, metrics::NumSamples("WebRTC.Video.AdaptChangesPerMinute.Cpu"));
1179   EXPECT_METRIC_EQ(
1180       1, metrics::NumEvents("WebRTC.Video.AdaptChangesPerMinute.Cpu", 8));
1181   EXPECT_METRIC_EQ(
1182       0, metrics::NumSamples("WebRTC.Video.AdaptChangesPerMinute.Quality"));
1183 
1184   // First RTP packet sent, scaling enabled.
1185   UpdateDataCounters(kFirstSsrc);
1186   statistics_proxy_->UpdateAdaptationSettings(kScalingEnabled,
1187                                               kScalingDisabled);
1188 
1189   // Adapt changes: 4, elapsed time: 120 sec => 2 per minute.
1190   statistics_proxy_->OnAdaptationChanged(VideoAdaptationReason::kCpu,
1191                                          cpu_counts, quality_counts);
1192   statistics_proxy_->OnAdaptationChanged(VideoAdaptationReason::kCpu,
1193                                          cpu_counts, quality_counts);
1194   statistics_proxy_->OnAdaptationChanged(VideoAdaptationReason::kCpu,
1195                                          cpu_counts, quality_counts);
1196   statistics_proxy_->OnAdaptationChanged(VideoAdaptationReason::kCpu,
1197                                          cpu_counts, quality_counts);
1198   fake_clock_.AdvanceTimeMilliseconds(120000);
1199 
1200   statistics_proxy_.reset();
1201   EXPECT_METRIC_EQ(1,
1202                    metrics::NumSamples(
1203                        "WebRTC.Video.Screenshare.AdaptChangesPerMinute.Cpu"));
1204   EXPECT_METRIC_EQ(
1205       1, metrics::NumEvents(
1206              "WebRTC.Video.Screenshare.AdaptChangesPerMinute.Cpu", 2));
1207   EXPECT_METRIC_EQ(
1208       0, metrics::NumSamples(
1209              "WebRTC.Video.Screenshare.AdaptChangesPerMinute.Quality"));
1210 }
1211 
TEST_F(SendStatisticsProxyTest,QualityLimitationReasonIsCpuWhenCpuIsResolutionLimited)1212 TEST_F(SendStatisticsProxyTest,
1213        QualityLimitationReasonIsCpuWhenCpuIsResolutionLimited) {
1214   VideoAdaptationCounters cpu_counts;
1215   VideoAdaptationCounters quality_counts;
1216 
1217   cpu_counts.resolution_adaptations = 1;
1218   statistics_proxy_->UpdateAdaptationSettings(kScalingEnabled, kScalingEnabled);
1219   statistics_proxy_->OnAdaptationChanged(VideoAdaptationReason::kCpu,
1220                                          cpu_counts, quality_counts);
1221 
1222   EXPECT_EQ(QualityLimitationReason::kCpu,
1223             statistics_proxy_->GetStats().quality_limitation_reason);
1224 }
1225 
TEST_F(SendStatisticsProxyTest,QualityLimitationReasonIsCpuWhenCpuIsFramerateLimited)1226 TEST_F(SendStatisticsProxyTest,
1227        QualityLimitationReasonIsCpuWhenCpuIsFramerateLimited) {
1228   VideoAdaptationCounters cpu_counts;
1229   VideoAdaptationCounters quality_counts;
1230 
1231   cpu_counts.fps_adaptations = 1;
1232 
1233   statistics_proxy_->UpdateAdaptationSettings(kScalingEnabled, kScalingEnabled);
1234   statistics_proxy_->OnAdaptationChanged(VideoAdaptationReason::kCpu,
1235                                          cpu_counts, quality_counts);
1236 
1237   EXPECT_EQ(QualityLimitationReason::kCpu,
1238             statistics_proxy_->GetStats().quality_limitation_reason);
1239 }
1240 
TEST_F(SendStatisticsProxyTest,QualityLimitationReasonIsBandwidthWhenQualityIsResolutionLimited)1241 TEST_F(SendStatisticsProxyTest,
1242        QualityLimitationReasonIsBandwidthWhenQualityIsResolutionLimited) {
1243   VideoAdaptationCounters cpu_counts;
1244   VideoAdaptationCounters quality_counts;
1245 
1246   quality_counts.resolution_adaptations = 1;
1247 
1248   statistics_proxy_->UpdateAdaptationSettings(kScalingEnabled, kScalingEnabled);
1249   statistics_proxy_->OnAdaptationChanged(VideoAdaptationReason::kQuality,
1250                                          cpu_counts, quality_counts);
1251 
1252   EXPECT_EQ(QualityLimitationReason::kBandwidth,
1253             statistics_proxy_->GetStats().quality_limitation_reason);
1254 }
1255 
TEST_F(SendStatisticsProxyTest,QualityLimitationReasonIsBandwidthWhenQualityIsFramerateLimited)1256 TEST_F(SendStatisticsProxyTest,
1257        QualityLimitationReasonIsBandwidthWhenQualityIsFramerateLimited) {
1258   VideoAdaptationCounters cpu_counts;
1259   VideoAdaptationCounters quality_counts;
1260 
1261   quality_counts.fps_adaptations = 1;
1262 
1263   statistics_proxy_->UpdateAdaptationSettings(kScalingEnabled, kScalingEnabled);
1264   statistics_proxy_->OnAdaptationChanged(VideoAdaptationReason::kQuality,
1265                                          cpu_counts, quality_counts);
1266 
1267   EXPECT_EQ(QualityLimitationReason::kBandwidth,
1268             statistics_proxy_->GetStats().quality_limitation_reason);
1269 }
1270 
TEST_F(SendStatisticsProxyTest,QualityLimitationReasonIsBandwidthWhenBothCpuAndQualityIsLimited)1271 TEST_F(SendStatisticsProxyTest,
1272        QualityLimitationReasonIsBandwidthWhenBothCpuAndQualityIsLimited) {
1273   VideoAdaptationCounters cpu_counts;
1274   VideoAdaptationCounters quality_counts;
1275 
1276   cpu_counts.resolution_adaptations = 1;
1277   quality_counts.resolution_adaptations = 1;
1278   statistics_proxy_->UpdateAdaptationSettings(kScalingEnabled, kScalingEnabled);
1279 
1280   // Even if the last adaptation reason is kCpu, if the counters indicate being
1281   // both CPU and quality (=bandwidth) limited, kBandwidth takes precedence.
1282   statistics_proxy_->OnAdaptationChanged(VideoAdaptationReason::kCpu,
1283                                          cpu_counts, quality_counts);
1284 
1285   EXPECT_EQ(QualityLimitationReason::kBandwidth,
1286             statistics_proxy_->GetStats().quality_limitation_reason);
1287 }
1288 
TEST_F(SendStatisticsProxyTest,QualityLimitationReasonIsNoneWhenNotLimited)1289 TEST_F(SendStatisticsProxyTest, QualityLimitationReasonIsNoneWhenNotLimited) {
1290   VideoAdaptationCounters cpu_counts;
1291   VideoAdaptationCounters quality_counts;
1292 
1293   // Observe a limitation due to CPU. This makes sure the test doesn't pass
1294   // due to "none" being the default value.
1295   cpu_counts.resolution_adaptations = 1;
1296   statistics_proxy_->UpdateAdaptationSettings(kScalingEnabled, kScalingEnabled);
1297   statistics_proxy_->OnAdaptationChanged(VideoAdaptationReason::kCpu,
1298                                          cpu_counts, quality_counts);
1299   // Go back to not being limited.
1300   cpu_counts.resolution_adaptations = 0;
1301   statistics_proxy_->OnAdaptationChanged(VideoAdaptationReason::kCpu,
1302                                          cpu_counts, quality_counts);
1303 
1304   EXPECT_EQ(QualityLimitationReason::kNone,
1305             statistics_proxy_->GetStats().quality_limitation_reason);
1306 }
1307 
TEST_F(SendStatisticsProxyTest,QualityLimitationDurationIncreasesWithTime)1308 TEST_F(SendStatisticsProxyTest, QualityLimitationDurationIncreasesWithTime) {
1309   VideoAdaptationCounters cpu_counts;
1310   VideoAdaptationCounters quality_counts;
1311 
1312   statistics_proxy_->UpdateAdaptationSettings(kScalingEnabled, kScalingEnabled);
1313   // Not limited for 3000 ms
1314   fake_clock_.AdvanceTimeMilliseconds(3000);
1315   // CPU limited for 2000 ms
1316   cpu_counts.resolution_adaptations = 1;
1317   statistics_proxy_->OnAdaptationChanged(VideoAdaptationReason::kCpu,
1318                                          cpu_counts, quality_counts);
1319   fake_clock_.AdvanceTimeMilliseconds(2000);
1320   // Bandwidth limited for 1000 ms
1321   cpu_counts.resolution_adaptations = 0;
1322   quality_counts.resolution_adaptations = 1;
1323   statistics_proxy_->OnAdaptationChanged(VideoAdaptationReason::kQuality,
1324                                          cpu_counts, quality_counts);
1325   fake_clock_.AdvanceTimeMilliseconds(1000);
1326   // CPU limited for another 2000 ms
1327   cpu_counts.resolution_adaptations = 1;
1328   quality_counts.resolution_adaptations = 0;
1329   statistics_proxy_->OnAdaptationChanged(VideoAdaptationReason::kCpu,
1330                                          cpu_counts, quality_counts);
1331   fake_clock_.AdvanceTimeMilliseconds(2000);
1332 
1333   auto quality_limitation_durations_ms =
1334       statistics_proxy_->GetStats().quality_limitation_durations_ms;
1335 
1336   EXPECT_EQ(3000,
1337             quality_limitation_durations_ms[QualityLimitationReason::kNone]);
1338   EXPECT_EQ(4000,
1339             quality_limitation_durations_ms[QualityLimitationReason::kCpu]);
1340   EXPECT_EQ(
1341       1000,
1342       quality_limitation_durations_ms[QualityLimitationReason::kBandwidth]);
1343   EXPECT_EQ(0,
1344             quality_limitation_durations_ms[QualityLimitationReason::kOther]);
1345 }
1346 
TEST_F(SendStatisticsProxyTest,QualityLimitationResolutionChangesDefaultZero)1347 TEST_F(SendStatisticsProxyTest, QualityLimitationResolutionChangesDefaultZero) {
1348   EXPECT_EQ(
1349       0u, statistics_proxy_->GetStats().quality_limitation_resolution_changes);
1350 }
1351 
TEST_F(SendStatisticsProxyTest,QualityLimitationResolutionChangesNotChangesWithOnlyDefaultAllocation)1352 TEST_F(SendStatisticsProxyTest,
1353        QualityLimitationResolutionChangesNotChangesWithOnlyDefaultAllocation) {
1354   VideoCodec codec;
1355   VideoBitrateAllocation allocation;
1356   statistics_proxy_->OnBitrateAllocationUpdated(codec, allocation);
1357   EXPECT_EQ(
1358       0u, statistics_proxy_->GetStats().quality_limitation_resolution_changes);
1359 }
1360 
TEST_F(SendStatisticsProxyTest,QualityLimitationResolutionChangesDoesNotIncreaseOnFirstAllocation)1361 TEST_F(SendStatisticsProxyTest,
1362        QualityLimitationResolutionChangesDoesNotIncreaseOnFirstAllocation) {
1363   VideoCodec codec;
1364   codec.simulcastStream[0].active = true;
1365   codec.simulcastStream[1].active = true;
1366   codec.simulcastStream[2].active = true;
1367   VideoBitrateAllocation allocation;
1368   allocation.SetBitrate(0, 0, 100);
1369   statistics_proxy_->OnBitrateAllocationUpdated(codec, allocation);
1370   EXPECT_EQ(
1371       0u, statistics_proxy_->GetStats().quality_limitation_resolution_changes);
1372 }
1373 
TEST_F(SendStatisticsProxyTest,QualityLimitationResolutionChangesWhenNewLayerGetsBandwidth)1374 TEST_F(SendStatisticsProxyTest,
1375        QualityLimitationResolutionChangesWhenNewLayerGetsBandwidth) {
1376   VideoCodec codec;
1377   codec.simulcastStream[0].active = true;
1378   codec.simulcastStream[1].active = true;
1379   codec.simulcastStream[2].active = true;
1380   VideoBitrateAllocation allocation;
1381   allocation.SetBitrate(0, 0, 100);
1382   statistics_proxy_->OnBitrateAllocationUpdated(codec, allocation);
1383   allocation.SetBitrate(1, 0, 100);
1384   statistics_proxy_->OnBitrateAllocationUpdated(codec, allocation);
1385   EXPECT_EQ(
1386       1u, statistics_proxy_->GetStats().quality_limitation_resolution_changes);
1387 }
1388 
TEST_F(SendStatisticsProxyTest,QualityLimitationResolutionDoesNotChangeWhenLayerSame)1389 TEST_F(SendStatisticsProxyTest,
1390        QualityLimitationResolutionDoesNotChangeWhenLayerSame) {
1391   VideoCodec codec;
1392   codec.simulcastStream[0].active = true;
1393   VideoBitrateAllocation allocation;
1394   allocation.SetBitrate(0, 0, 100);
1395   statistics_proxy_->OnBitrateAllocationUpdated(codec, allocation);
1396   // Layer 0 got more bandwidth, but still only one layer on
1397   allocation.SetBitrate(0, 0, 200);
1398   statistics_proxy_->OnBitrateAllocationUpdated(codec, allocation);
1399   EXPECT_EQ(
1400       0u, statistics_proxy_->GetStats().quality_limitation_resolution_changes);
1401 }
1402 
TEST_F(SendStatisticsProxyTest,QualityLimitationResolutionChangesWithTogglingLayers)1403 TEST_F(SendStatisticsProxyTest,
1404        QualityLimitationResolutionChangesWithTogglingLayers) {
1405   VideoCodec codec;
1406   codec.simulcastStream[0].active = true;
1407   codec.simulcastStream[1].active = true;
1408   codec.simulcastStream[2].active = true;
1409   VideoBitrateAllocation allocation;
1410   allocation.SetBitrate(0, 0, 100);
1411   statistics_proxy_->OnBitrateAllocationUpdated(codec, allocation);
1412   EXPECT_EQ(
1413       0u, statistics_proxy_->GetStats().quality_limitation_resolution_changes);
1414   allocation.SetBitrate(1, 0, 300);
1415   allocation.SetBitrate(2, 0, 500);
1416   statistics_proxy_->OnBitrateAllocationUpdated(codec, allocation);
1417   EXPECT_EQ(
1418       1u, statistics_proxy_->GetStats().quality_limitation_resolution_changes);
1419   // Layer 2 off
1420   allocation.SetBitrate(2, 0, 0);
1421   statistics_proxy_->OnBitrateAllocationUpdated(codec, allocation);
1422   EXPECT_EQ(
1423       2u, statistics_proxy_->GetStats().quality_limitation_resolution_changes);
1424   // Layer 2 back on
1425   allocation.SetBitrate(2, 0, 500);
1426   statistics_proxy_->OnBitrateAllocationUpdated(codec, allocation);
1427   EXPECT_EQ(
1428       3u, statistics_proxy_->GetStats().quality_limitation_resolution_changes);
1429   allocation.SetBitrate(0, 0, 0);
1430   allocation.SetBitrate(1, 0, 0);
1431   allocation.SetBitrate(2, 0, 0);
1432   // All layers off
1433   statistics_proxy_->OnBitrateAllocationUpdated(codec, allocation);
1434   EXPECT_EQ(
1435       4u, statistics_proxy_->GetStats().quality_limitation_resolution_changes);
1436 }
1437 
TEST_F(SendStatisticsProxyTest,QualityLimitationResolutionDoesNotUpdateOnCodecSimulcastStreamChanges)1438 TEST_F(SendStatisticsProxyTest,
1439        QualityLimitationResolutionDoesNotUpdateOnCodecSimulcastStreamChanges) {
1440   VideoCodec codec;
1441   // 3 layers
1442   codec.simulcastStream[0].active = true;
1443   codec.simulcastStream[1].active = true;
1444   codec.simulcastStream[2].active = true;
1445   VideoBitrateAllocation allocation;
1446   allocation.SetBitrate(0, 0, 500);
1447   allocation.SetBitrate(1, 0, 500);
1448   allocation.SetBitrate(2, 0, 500);
1449   statistics_proxy_->OnBitrateAllocationUpdated(codec, allocation);
1450   EXPECT_EQ(
1451       0u, statistics_proxy_->GetStats().quality_limitation_resolution_changes);
1452 
1453   // Down to one layer now, triggered by a config change
1454   codec.numberOfSimulcastStreams = 1;
1455   codec.simulcastStream[1].active = false;
1456   codec.simulcastStream[2].active = false;
1457   allocation.SetBitrate(0, 0, 100);
1458   statistics_proxy_->OnBitrateAllocationUpdated(codec, allocation);
1459   EXPECT_EQ(
1460       0u, statistics_proxy_->GetStats().quality_limitation_resolution_changes);
1461 
1462   // Up to 3 layers again.
1463   codec.numberOfSimulcastStreams = 3;
1464   codec.simulcastStream[1].active = true;
1465   codec.simulcastStream[2].active = true;
1466   allocation.SetBitrate(0, 0, 500);
1467   allocation.SetBitrate(1, 0, 500);
1468   allocation.SetBitrate(2, 0, 500);
1469   statistics_proxy_->OnBitrateAllocationUpdated(codec, allocation);
1470   EXPECT_EQ(
1471       0u, statistics_proxy_->GetStats().quality_limitation_resolution_changes);
1472 }
1473 
TEST_F(SendStatisticsProxyTest,QualityLimitationResolutionDoesNotUpdateForSpatialLayerChanges)1474 TEST_F(SendStatisticsProxyTest,
1475        QualityLimitationResolutionDoesNotUpdateForSpatialLayerChanges) {
1476   VideoCodec codec;
1477   codec.simulcastStream[0].active = true;
1478   codec.spatialLayers[0].active = true;
1479   codec.spatialLayers[1].active = true;
1480   codec.spatialLayers[2].active = true;
1481   VideoBitrateAllocation allocation;
1482   allocation.SetBitrate(0, 0, 500);
1483   allocation.SetBitrate(1, 0, 500);
1484   allocation.SetBitrate(2, 0, 500);
1485   statistics_proxy_->OnBitrateAllocationUpdated(codec, allocation);
1486   EXPECT_EQ(
1487       0u, statistics_proxy_->GetStats().quality_limitation_resolution_changes);
1488 
1489   // Down to one layer now, triggered by a config change
1490   codec.spatialLayers[1].active = false;
1491   codec.spatialLayers[2].active = false;
1492   allocation.SetBitrate(0, 0, 100);
1493   statistics_proxy_->OnBitrateAllocationUpdated(codec, allocation);
1494   EXPECT_EQ(
1495       0u, statistics_proxy_->GetStats().quality_limitation_resolution_changes);
1496 
1497   // Up to 3 layers again.
1498   codec.spatialLayers[1].active = true;
1499   codec.spatialLayers[2].active = true;
1500   allocation.SetBitrate(0, 0, 500);
1501   allocation.SetBitrate(1, 0, 500);
1502   allocation.SetBitrate(2, 0, 500);
1503   statistics_proxy_->OnBitrateAllocationUpdated(codec, allocation);
1504   EXPECT_EQ(
1505       0u, statistics_proxy_->GetStats().quality_limitation_resolution_changes);
1506 }
1507 
TEST_F(SendStatisticsProxyTest,QualityLimitationReasonsAreCorrectForContentType)1508 TEST_F(SendStatisticsProxyTest,
1509        QualityLimitationReasonsAreCorrectForContentType) {
1510   // Realtime case.
1511   // Configure two streams.
1512   VideoEncoderConfig config;
1513   config.content_type = VideoEncoderConfig::ContentType::kRealtimeVideo;
1514   config.number_of_streams = 2;
1515   VideoStream stream1;
1516   stream1.width = kWidth / 2;
1517   stream1.height = kHeight / 2;
1518   VideoStream stream2;
1519   stream2.width = kWidth;
1520   stream2.height = kHeight;
1521   statistics_proxy_->OnEncoderReconfigured(config, {stream1, stream2});
1522   EXPECT_FALSE(statistics_proxy_->GetStats().bw_limited_resolution);
1523   EXPECT_FALSE(statistics_proxy_->GetStats().bw_limited_framerate);
1524   EXPECT_EQ(statistics_proxy_->GetStats().quality_limitation_reason,
1525             QualityLimitationReason::kNone);
1526   // Bw disabled one layer.
1527   VideoCodec codec;
1528   codec.numberOfSimulcastStreams = 2;
1529   codec.simulcastStream[0].active = true;
1530   codec.simulcastStream[1].active = true;
1531   VideoBitrateAllocation allocation;
1532   // Some positive bitrate only on the first stream.
1533   allocation.SetBitrate(0, 0, 10000);
1534   allocation.SetBitrate(1, 0, 0);
1535   allocation.set_bw_limited(true);
1536   statistics_proxy_->OnBitrateAllocationUpdated(codec, allocation);
1537   EXPECT_TRUE(statistics_proxy_->GetStats().bw_limited_resolution);
1538   EXPECT_FALSE(statistics_proxy_->GetStats().bw_limited_framerate);
1539   EXPECT_EQ(statistics_proxy_->GetStats().quality_limitation_reason,
1540             QualityLimitationReason::kBandwidth);
1541   // Bw enabled all layers.
1542   allocation.SetBitrate(1, 0, 10000);
1543   allocation.set_bw_limited(false);
1544   statistics_proxy_->OnBitrateAllocationUpdated(codec, allocation);
1545   EXPECT_FALSE(statistics_proxy_->GetStats().bw_limited_resolution);
1546   EXPECT_FALSE(statistics_proxy_->GetStats().bw_limited_framerate);
1547   EXPECT_EQ(statistics_proxy_->GetStats().quality_limitation_reason,
1548             QualityLimitationReason::kNone);
1549 
1550   // Screencast case
1551   // Configure two streams.
1552   config.content_type = VideoEncoderConfig::ContentType::kScreen;
1553   config.number_of_streams = 2;
1554   stream1.width = kWidth;
1555   stream1.height = kHeight;
1556   statistics_proxy_->OnEncoderReconfigured(config, {stream1, stream2});
1557   EXPECT_FALSE(statistics_proxy_->GetStats().bw_limited_framerate);
1558   EXPECT_FALSE(statistics_proxy_->GetStats().bw_limited_resolution);
1559   EXPECT_EQ(statistics_proxy_->GetStats().quality_limitation_reason,
1560             QualityLimitationReason::kNone);
1561   // Bw disabled one layer.
1562   // Some positive bitrate only on the second stream.
1563   allocation.SetBitrate(0, 0, 10000);
1564   allocation.SetBitrate(1, 0, 0);
1565   allocation.set_bw_limited(true);
1566   statistics_proxy_->OnBitrateAllocationUpdated(codec, allocation);
1567   EXPECT_TRUE(statistics_proxy_->GetStats().bw_limited_framerate);
1568   EXPECT_FALSE(statistics_proxy_->GetStats().bw_limited_resolution);
1569   EXPECT_EQ(statistics_proxy_->GetStats().quality_limitation_reason,
1570             QualityLimitationReason::kBandwidth);
1571   // Bw enabled all layers.
1572   allocation.SetBitrate(1, 0, 10000);
1573   allocation.set_bw_limited(false);
1574   statistics_proxy_->OnBitrateAllocationUpdated(codec, allocation);
1575   EXPECT_FALSE(statistics_proxy_->GetStats().bw_limited_resolution);
1576   EXPECT_FALSE(statistics_proxy_->GetStats().bw_limited_resolution);
1577   EXPECT_EQ(statistics_proxy_->GetStats().quality_limitation_reason,
1578             QualityLimitationReason::kNone);
1579 }
1580 
TEST_F(SendStatisticsProxyTest,SwitchContentTypeUpdatesHistograms)1581 TEST_F(SendStatisticsProxyTest, SwitchContentTypeUpdatesHistograms) {
1582   for (int i = 0; i < SendStatisticsProxy::kMinRequiredMetricsSamples; ++i)
1583     statistics_proxy_->OnIncomingFrame(kWidth, kHeight);
1584 
1585   // No switch, stats should not be updated.
1586   VideoEncoderConfig config;
1587   config.content_type = VideoEncoderConfig::ContentType::kRealtimeVideo;
1588   statistics_proxy_->OnEncoderReconfigured(config, {});
1589   EXPECT_METRIC_EQ(0, metrics::NumSamples("WebRTC.Video.InputWidthInPixels"));
1590 
1591   // Switch to screenshare, real-time stats should be updated.
1592   config.content_type = VideoEncoderConfig::ContentType::kScreen;
1593   statistics_proxy_->OnEncoderReconfigured(config, {});
1594   EXPECT_METRIC_EQ(1, metrics::NumSamples("WebRTC.Video.InputWidthInPixels"));
1595 }
1596 
TEST_F(SendStatisticsProxyTest,InputResolutionHistogramsAreUpdated)1597 TEST_F(SendStatisticsProxyTest, InputResolutionHistogramsAreUpdated) {
1598   for (int i = 0; i < SendStatisticsProxy::kMinRequiredMetricsSamples; ++i)
1599     statistics_proxy_->OnIncomingFrame(kWidth, kHeight);
1600 
1601   statistics_proxy_.reset();
1602   EXPECT_METRIC_EQ(1, metrics::NumSamples("WebRTC.Video.InputWidthInPixels"));
1603   EXPECT_METRIC_EQ(
1604       1, metrics::NumEvents("WebRTC.Video.InputWidthInPixels", kWidth));
1605   EXPECT_METRIC_EQ(1, metrics::NumSamples("WebRTC.Video.InputHeightInPixels"));
1606   EXPECT_METRIC_EQ(
1607       1, metrics::NumEvents("WebRTC.Video.InputHeightInPixels", kHeight));
1608 }
1609 
TEST_F(SendStatisticsProxyTest,SentResolutionHistogramsAreUpdated)1610 TEST_F(SendStatisticsProxyTest, SentResolutionHistogramsAreUpdated) {
1611   const int64_t kMaxEncodedFrameWindowMs = 800;
1612   const int kFps = 5;
1613   const int kNumFramesPerWindow = kFps * kMaxEncodedFrameWindowMs / 1000;
1614   const int kMinSamples =  // Sample added when removed from EncodedFrameMap.
1615       SendStatisticsProxy::kMinRequiredMetricsSamples + kNumFramesPerWindow;
1616   EncodedImage encoded_image;
1617 
1618   // Not enough samples, stats should not be updated.
1619   for (int i = 0; i < kMinSamples - 1; ++i) {
1620     fake_clock_.AdvanceTimeMilliseconds(1000 / kFps);
1621     encoded_image.SetTimestamp(encoded_image.Timestamp() + 90 * 1000 / kFps);
1622     statistics_proxy_->OnSendEncodedImage(encoded_image, nullptr);
1623   }
1624   SetUp();  // Reset stats proxy also causes histograms to be reported.
1625   EXPECT_METRIC_EQ(0, metrics::NumSamples("WebRTC.Video.SentWidthInPixels"));
1626   EXPECT_METRIC_EQ(0, metrics::NumSamples("WebRTC.Video.SentHeightInPixels"));
1627 
1628   // Enough samples, max resolution per frame should be reported.
1629   encoded_image.SetTimestamp(0xffff0000);  // Will wrap.
1630   for (int i = 0; i < kMinSamples; ++i) {
1631     fake_clock_.AdvanceTimeMilliseconds(1000 / kFps);
1632     encoded_image.SetTimestamp(encoded_image.Timestamp() + 90 * 1000 / kFps);
1633     encoded_image._encodedWidth = kWidth;
1634     encoded_image._encodedHeight = kHeight;
1635     statistics_proxy_->OnSendEncodedImage(encoded_image, nullptr);
1636     encoded_image._encodedWidth = kWidth / 2;
1637     encoded_image._encodedHeight = kHeight / 2;
1638     statistics_proxy_->OnSendEncodedImage(encoded_image, nullptr);
1639   }
1640 
1641   statistics_proxy_.reset();
1642   EXPECT_METRIC_EQ(1, metrics::NumSamples("WebRTC.Video.SentWidthInPixels"));
1643   EXPECT_METRIC_EQ(
1644       1, metrics::NumEvents("WebRTC.Video.SentWidthInPixels", kWidth));
1645   EXPECT_METRIC_EQ(1, metrics::NumSamples("WebRTC.Video.SentHeightInPixels"));
1646   EXPECT_METRIC_EQ(
1647       1, metrics::NumEvents("WebRTC.Video.SentHeightInPixels", kHeight));
1648 }
1649 
TEST_F(SendStatisticsProxyTest,InputFpsHistogramIsUpdated)1650 TEST_F(SendStatisticsProxyTest, InputFpsHistogramIsUpdated) {
1651   const int kFps = 20;
1652   const int kMinPeriodicSamples = 6;
1653   int frames = kMinPeriodicSamples * kFpsPeriodicIntervalMs * kFps / 1000;
1654   for (int i = 0; i <= frames; ++i) {
1655     fake_clock_.AdvanceTimeMilliseconds(1000 / kFps);
1656     statistics_proxy_->OnIncomingFrame(kWidth, kHeight);
1657   }
1658   statistics_proxy_.reset();
1659   EXPECT_METRIC_EQ(1, metrics::NumSamples("WebRTC.Video.InputFramesPerSecond"));
1660   EXPECT_METRIC_EQ(
1661       1, metrics::NumEvents("WebRTC.Video.InputFramesPerSecond", kFps));
1662 }
1663 
TEST_F(SendStatisticsProxyTest,SentFpsHistogramIsUpdated)1664 TEST_F(SendStatisticsProxyTest, SentFpsHistogramIsUpdated) {
1665   EncodedImage encoded_image;
1666   const int kFps = 20;
1667   const int kMinPeriodicSamples = 6;
1668   int frames = kMinPeriodicSamples * kFpsPeriodicIntervalMs * kFps / 1000 + 1;
1669   for (int i = 0; i < frames; ++i) {
1670     fake_clock_.AdvanceTimeMilliseconds(1000 / kFps);
1671     encoded_image.SetTimestamp(encoded_image.Timestamp() + 1);
1672     statistics_proxy_->OnSendEncodedImage(encoded_image, nullptr);
1673     // Frame with same timestamp should not be counted.
1674     statistics_proxy_->OnSendEncodedImage(encoded_image, nullptr);
1675   }
1676   statistics_proxy_.reset();
1677   EXPECT_METRIC_EQ(1, metrics::NumSamples("WebRTC.Video.SentFramesPerSecond"));
1678   EXPECT_METRIC_EQ(
1679       1, metrics::NumEvents("WebRTC.Video.SentFramesPerSecond", kFps));
1680 }
1681 
TEST_F(SendStatisticsProxyTest,InputFpsHistogramExcludesSuspendedTime)1682 TEST_F(SendStatisticsProxyTest, InputFpsHistogramExcludesSuspendedTime) {
1683   const int kFps = 20;
1684   const int kSuspendTimeMs = 10000;
1685   const int kMinPeriodicSamples = 6;
1686   int frames = kMinPeriodicSamples * kFpsPeriodicIntervalMs * kFps / 1000;
1687   for (int i = 0; i < frames; ++i) {
1688     fake_clock_.AdvanceTimeMilliseconds(1000 / kFps);
1689     statistics_proxy_->OnIncomingFrame(kWidth, kHeight);
1690   }
1691   // Suspend.
1692   statistics_proxy_->OnSuspendChange(true);
1693   fake_clock_.AdvanceTimeMilliseconds(kSuspendTimeMs);
1694 
1695   for (int i = 0; i < frames; ++i) {
1696     fake_clock_.AdvanceTimeMilliseconds(1000 / kFps);
1697     statistics_proxy_->OnIncomingFrame(kWidth, kHeight);
1698   }
1699   // Suspended time interval should not affect the framerate.
1700   statistics_proxy_.reset();
1701   EXPECT_METRIC_EQ(1, metrics::NumSamples("WebRTC.Video.InputFramesPerSecond"));
1702   EXPECT_METRIC_EQ(
1703       1, metrics::NumEvents("WebRTC.Video.InputFramesPerSecond", kFps));
1704 }
1705 
TEST_F(SendStatisticsProxyTest,SentFpsHistogramExcludesSuspendedTime)1706 TEST_F(SendStatisticsProxyTest, SentFpsHistogramExcludesSuspendedTime) {
1707   EncodedImage encoded_image;
1708   const int kFps = 20;
1709   const int kSuspendTimeMs = 10000;
1710   const int kMinPeriodicSamples = 6;
1711   int frames = kMinPeriodicSamples * kFpsPeriodicIntervalMs * kFps / 1000;
1712   for (int i = 0; i < frames; ++i) {
1713     fake_clock_.AdvanceTimeMilliseconds(1000 / kFps);
1714     encoded_image.SetTimestamp(i + 1);
1715     statistics_proxy_->OnSendEncodedImage(encoded_image, nullptr);
1716   }
1717   // Suspend.
1718   statistics_proxy_->OnSuspendChange(true);
1719   fake_clock_.AdvanceTimeMilliseconds(kSuspendTimeMs);
1720 
1721   for (int i = 0; i < frames; ++i) {
1722     fake_clock_.AdvanceTimeMilliseconds(1000 / kFps);
1723     encoded_image.SetTimestamp(i + 1);
1724     statistics_proxy_->OnSendEncodedImage(encoded_image, nullptr);
1725   }
1726   // Suspended time interval should not affect the framerate.
1727   statistics_proxy_.reset();
1728   EXPECT_METRIC_EQ(1, metrics::NumSamples("WebRTC.Video.SentFramesPerSecond"));
1729   EXPECT_METRIC_EQ(
1730       1, metrics::NumEvents("WebRTC.Video.SentFramesPerSecond", kFps));
1731 }
1732 
TEST_F(SendStatisticsProxyTest,CpuLimitedHistogramNotUpdatedWhenDisabled)1733 TEST_F(SendStatisticsProxyTest, CpuLimitedHistogramNotUpdatedWhenDisabled) {
1734   statistics_proxy_->UpdateAdaptationSettings(kResolutionScalingDisabled,
1735                                               kResolutionScalingDisabled);
1736 
1737   for (int i = 0; i < SendStatisticsProxy::kMinRequiredMetricsSamples; ++i)
1738     statistics_proxy_->OnIncomingFrame(kWidth, kHeight);
1739 
1740   statistics_proxy_.reset();
1741   EXPECT_METRIC_EQ(
1742       0, metrics::NumSamples("WebRTC.Video.CpuLimitedResolutionInPercent"));
1743 }
1744 
TEST_F(SendStatisticsProxyTest,CpuLimitedHistogramUpdated)1745 TEST_F(SendStatisticsProxyTest, CpuLimitedHistogramUpdated) {
1746   VideoAdaptationCounters cpu_counts;
1747   VideoAdaptationCounters quality_counts;
1748   cpu_counts.resolution_adaptations = 0;
1749   statistics_proxy_->UpdateAdaptationSettings(kScalingEnabled, kScalingEnabled);
1750 
1751   for (int i = 0; i < SendStatisticsProxy::kMinRequiredMetricsSamples; ++i)
1752     statistics_proxy_->OnIncomingFrame(kWidth, kHeight);
1753 
1754   cpu_counts.resolution_adaptations = 1;
1755   statistics_proxy_->OnAdaptationChanged(VideoAdaptationReason::kCpu,
1756                                          cpu_counts, quality_counts);
1757 
1758   for (int i = 0; i < SendStatisticsProxy::kMinRequiredMetricsSamples; ++i)
1759     statistics_proxy_->OnIncomingFrame(kWidth, kHeight);
1760 
1761   statistics_proxy_.reset();
1762   EXPECT_METRIC_EQ(
1763       1, metrics::NumSamples("WebRTC.Video.CpuLimitedResolutionInPercent"));
1764   EXPECT_METRIC_EQ(
1765       1, metrics::NumEvents("WebRTC.Video.CpuLimitedResolutionInPercent", 50));
1766 }
1767 
TEST_F(SendStatisticsProxyTest,LifetimeHistogramIsUpdated)1768 TEST_F(SendStatisticsProxyTest, LifetimeHistogramIsUpdated) {
1769   const int64_t kTimeSec = 3;
1770   fake_clock_.AdvanceTimeMilliseconds(kTimeSec * 1000);
1771   statistics_proxy_.reset();
1772   EXPECT_METRIC_EQ(
1773       1, metrics::NumSamples("WebRTC.Video.SendStreamLifetimeInSeconds"));
1774   EXPECT_METRIC_EQ(
1775       1,
1776       metrics::NumEvents("WebRTC.Video.SendStreamLifetimeInSeconds", kTimeSec));
1777 }
1778 
TEST_F(SendStatisticsProxyTest,CodecTypeHistogramIsUpdated)1779 TEST_F(SendStatisticsProxyTest, CodecTypeHistogramIsUpdated) {
1780   fake_clock_.AdvanceTimeMilliseconds(metrics::kMinRunTimeInSeconds * 1000);
1781   statistics_proxy_.reset();
1782   EXPECT_METRIC_EQ(1, metrics::NumSamples("WebRTC.Video.Encoder.CodecType"));
1783 }
1784 
TEST_F(SendStatisticsProxyTest,PauseEventHistogramIsUpdated)1785 TEST_F(SendStatisticsProxyTest, PauseEventHistogramIsUpdated) {
1786   // First RTP packet sent.
1787   UpdateDataCounters(kFirstSsrc);
1788 
1789   // Min runtime has passed.
1790   fake_clock_.AdvanceTimeMilliseconds(metrics::kMinRunTimeInSeconds * 1000);
1791   statistics_proxy_.reset();
1792   EXPECT_METRIC_EQ(1, metrics::NumSamples("WebRTC.Video.NumberOfPauseEvents"));
1793   EXPECT_METRIC_EQ(1,
1794                    metrics::NumEvents("WebRTC.Video.NumberOfPauseEvents", 0));
1795 }
1796 
TEST_F(SendStatisticsProxyTest,PauseEventHistogramIsNotUpdatedIfMinRuntimeHasNotPassed)1797 TEST_F(SendStatisticsProxyTest,
1798        PauseEventHistogramIsNotUpdatedIfMinRuntimeHasNotPassed) {
1799   // First RTP packet sent.
1800   UpdateDataCounters(kFirstSsrc);
1801 
1802   // Min runtime has not passed.
1803   fake_clock_.AdvanceTimeMilliseconds(metrics::kMinRunTimeInSeconds * 1000 - 1);
1804   statistics_proxy_.reset();
1805   EXPECT_METRIC_EQ(0, metrics::NumSamples("WebRTC.Video.NumberOfPauseEvents"));
1806   EXPECT_METRIC_EQ(0, metrics::NumSamples("WebRTC.Video.PausedTimeInPercent"));
1807 }
1808 
TEST_F(SendStatisticsProxyTest,PauseEventHistogramIsNotUpdatedIfNoMediaIsSent)1809 TEST_F(SendStatisticsProxyTest,
1810        PauseEventHistogramIsNotUpdatedIfNoMediaIsSent) {
1811   // First RTP packet not sent.
1812   fake_clock_.AdvanceTimeMilliseconds(metrics::kMinRunTimeInSeconds * 1000);
1813   statistics_proxy_.reset();
1814   EXPECT_METRIC_EQ(0, metrics::NumSamples("WebRTC.Video.NumberOfPauseEvents"));
1815 }
1816 
TEST_F(SendStatisticsProxyTest,NoPauseEvent)1817 TEST_F(SendStatisticsProxyTest, NoPauseEvent) {
1818   // First RTP packet sent and min runtime passed.
1819   UpdateDataCounters(kFirstSsrc);
1820 
1821   // No change. Video: 10000 ms, paused: 0 ms (0%).
1822   statistics_proxy_->OnSetEncoderTargetRate(50000);
1823   fake_clock_.AdvanceTimeMilliseconds(metrics::kMinRunTimeInSeconds * 1000);
1824   statistics_proxy_->OnSetEncoderTargetRate(0);  // VideoSendStream::Stop
1825 
1826   statistics_proxy_.reset();
1827   EXPECT_METRIC_EQ(1, metrics::NumSamples("WebRTC.Video.NumberOfPauseEvents"));
1828   EXPECT_METRIC_EQ(1,
1829                    metrics::NumEvents("WebRTC.Video.NumberOfPauseEvents", 0));
1830   EXPECT_METRIC_EQ(1, metrics::NumSamples("WebRTC.Video.PausedTimeInPercent"));
1831   EXPECT_METRIC_EQ(1,
1832                    metrics::NumEvents("WebRTC.Video.PausedTimeInPercent", 0));
1833 }
1834 
TEST_F(SendStatisticsProxyTest,OnePauseEvent)1835 TEST_F(SendStatisticsProxyTest, OnePauseEvent) {
1836   // First RTP packet sent and min runtime passed.
1837   UpdateDataCounters(kFirstSsrc);
1838 
1839   // One change. Video: 7000 ms, paused: 3000 ms (30%).
1840   statistics_proxy_->OnSetEncoderTargetRate(50000);
1841   fake_clock_.AdvanceTimeMilliseconds(7000);
1842   statistics_proxy_->OnSetEncoderTargetRate(0);
1843   fake_clock_.AdvanceTimeMilliseconds(3000);
1844   statistics_proxy_->OnSetEncoderTargetRate(0);  // VideoSendStream::Stop
1845 
1846   statistics_proxy_.reset();
1847   EXPECT_METRIC_EQ(1, metrics::NumSamples("WebRTC.Video.NumberOfPauseEvents"));
1848   EXPECT_METRIC_EQ(1,
1849                    metrics::NumEvents("WebRTC.Video.NumberOfPauseEvents", 1));
1850   EXPECT_METRIC_EQ(1, metrics::NumSamples("WebRTC.Video.PausedTimeInPercent"));
1851   EXPECT_METRIC_EQ(1,
1852                    metrics::NumEvents("WebRTC.Video.PausedTimeInPercent", 30));
1853 }
1854 
TEST_F(SendStatisticsProxyTest,TwoPauseEvents)1855 TEST_F(SendStatisticsProxyTest, TwoPauseEvents) {
1856   // First RTP packet sent.
1857   UpdateDataCounters(kFirstSsrc);
1858 
1859   // Two changes. Video: 19000 ms, paused: 1000 ms (5%).
1860   statistics_proxy_->OnSetEncoderTargetRate(0);
1861   fake_clock_.AdvanceTimeMilliseconds(1000);
1862   statistics_proxy_->OnSetEncoderTargetRate(50000);  // Starts on bitrate > 0.
1863   fake_clock_.AdvanceTimeMilliseconds(7000);
1864   statistics_proxy_->OnSetEncoderTargetRate(60000);
1865   fake_clock_.AdvanceTimeMilliseconds(3000);
1866   statistics_proxy_->OnSetEncoderTargetRate(0);
1867   fake_clock_.AdvanceTimeMilliseconds(250);
1868   statistics_proxy_->OnSetEncoderTargetRate(0);
1869   fake_clock_.AdvanceTimeMilliseconds(750);
1870   statistics_proxy_->OnSetEncoderTargetRate(60000);
1871   fake_clock_.AdvanceTimeMilliseconds(5000);
1872   statistics_proxy_->OnSetEncoderTargetRate(50000);
1873   fake_clock_.AdvanceTimeMilliseconds(4000);
1874   statistics_proxy_->OnSetEncoderTargetRate(0);  // VideoSendStream::Stop
1875 
1876   statistics_proxy_.reset();
1877   EXPECT_METRIC_EQ(1, metrics::NumSamples("WebRTC.Video.NumberOfPauseEvents"));
1878   EXPECT_METRIC_EQ(1,
1879                    metrics::NumEvents("WebRTC.Video.NumberOfPauseEvents", 2));
1880   EXPECT_METRIC_EQ(1, metrics::NumSamples("WebRTC.Video.PausedTimeInPercent"));
1881   EXPECT_METRIC_EQ(1,
1882                    metrics::NumEvents("WebRTC.Video.PausedTimeInPercent", 5));
1883 }
1884 
TEST_F(SendStatisticsProxyTest,PausedTimeHistogramIsNotUpdatedIfMinRuntimeHasNotPassed)1885 TEST_F(SendStatisticsProxyTest,
1886        PausedTimeHistogramIsNotUpdatedIfMinRuntimeHasNotPassed) {
1887   // First RTP packet sent.
1888   UpdateDataCounters(kFirstSsrc);
1889   fake_clock_.AdvanceTimeMilliseconds(metrics::kMinRunTimeInSeconds * 1000);
1890 
1891   // Min runtime has not passed.
1892   statistics_proxy_->OnSetEncoderTargetRate(50000);
1893   fake_clock_.AdvanceTimeMilliseconds(metrics::kMinRunTimeInSeconds * 1000 - 1);
1894   statistics_proxy_->OnSetEncoderTargetRate(0);  // VideoSendStream::Stop
1895 
1896   statistics_proxy_.reset();
1897   EXPECT_METRIC_EQ(0, metrics::NumSamples("WebRTC.Video.PausedTimeInPercent"));
1898 }
1899 
TEST_F(SendStatisticsProxyTest,VerifyQpHistogramStats_Vp8)1900 TEST_F(SendStatisticsProxyTest, VerifyQpHistogramStats_Vp8) {
1901   EncodedImage encoded_image;
1902   CodecSpecificInfo codec_info;
1903   codec_info.codecType = kVideoCodecVP8;
1904 
1905   for (int i = 0; i < SendStatisticsProxy::kMinRequiredMetricsSamples; ++i) {
1906     encoded_image.SetSpatialIndex(0);
1907     encoded_image.qp_ = kQpIdx0;
1908     statistics_proxy_->OnSendEncodedImage(encoded_image, &codec_info);
1909     encoded_image.SetSpatialIndex(1);
1910     encoded_image.qp_ = kQpIdx1;
1911     statistics_proxy_->OnSendEncodedImage(encoded_image, &codec_info);
1912   }
1913   statistics_proxy_.reset();
1914   EXPECT_METRIC_EQ(1, metrics::NumSamples("WebRTC.Video.Encoded.Qp.Vp8.S0"));
1915   EXPECT_METRIC_EQ(
1916       1, metrics::NumEvents("WebRTC.Video.Encoded.Qp.Vp8.S0", kQpIdx0));
1917   EXPECT_METRIC_EQ(1, metrics::NumSamples("WebRTC.Video.Encoded.Qp.Vp8.S1"));
1918   EXPECT_METRIC_EQ(
1919       1, metrics::NumEvents("WebRTC.Video.Encoded.Qp.Vp8.S1", kQpIdx1));
1920 }
1921 
TEST_F(SendStatisticsProxyTest,VerifyQpHistogramStats_Vp8OneSsrc)1922 TEST_F(SendStatisticsProxyTest, VerifyQpHistogramStats_Vp8OneSsrc) {
1923   test::ScopedKeyValueConfig field_trials;
1924   VideoSendStream::Config config(nullptr);
1925   config.rtp.ssrcs.push_back(kFirstSsrc);
1926   statistics_proxy_.reset(new SendStatisticsProxy(
1927       &fake_clock_, config, VideoEncoderConfig::ContentType::kRealtimeVideo,
1928       field_trials));
1929 
1930   EncodedImage encoded_image;
1931   CodecSpecificInfo codec_info;
1932   codec_info.codecType = kVideoCodecVP8;
1933 
1934   for (int i = 0; i < SendStatisticsProxy::kMinRequiredMetricsSamples; ++i) {
1935     encoded_image.SetSpatialIndex(0);
1936     encoded_image.qp_ = kQpIdx0;
1937     statistics_proxy_->OnSendEncodedImage(encoded_image, &codec_info);
1938   }
1939   statistics_proxy_.reset();
1940   EXPECT_METRIC_EQ(1, metrics::NumSamples("WebRTC.Video.Encoded.Qp.Vp8"));
1941   EXPECT_METRIC_EQ(1,
1942                    metrics::NumEvents("WebRTC.Video.Encoded.Qp.Vp8", kQpIdx0));
1943 }
1944 
TEST_F(SendStatisticsProxyTest,VerifyQpHistogramStats_Vp9)1945 TEST_F(SendStatisticsProxyTest, VerifyQpHistogramStats_Vp9) {
1946   EncodedImage encoded_image;
1947   CodecSpecificInfo codec_info;
1948   codec_info.codecType = kVideoCodecVP9;
1949   codec_info.codecSpecific.VP9.num_spatial_layers = 2;
1950 
1951   for (int i = 0; i < SendStatisticsProxy::kMinRequiredMetricsSamples; ++i) {
1952     encoded_image.qp_ = kQpIdx0;
1953     encoded_image.SetSpatialIndex(0);
1954     statistics_proxy_->OnSendEncodedImage(encoded_image, &codec_info);
1955     encoded_image.qp_ = kQpIdx1;
1956     encoded_image.SetSpatialIndex(1);
1957     statistics_proxy_->OnSendEncodedImage(encoded_image, &codec_info);
1958   }
1959   statistics_proxy_.reset();
1960   EXPECT_METRIC_EQ(1, metrics::NumSamples("WebRTC.Video.Encoded.Qp.Vp9.S0"));
1961   EXPECT_METRIC_EQ(
1962       1, metrics::NumEvents("WebRTC.Video.Encoded.Qp.Vp9.S0", kQpIdx0));
1963   EXPECT_METRIC_EQ(1, metrics::NumSamples("WebRTC.Video.Encoded.Qp.Vp9.S1"));
1964   EXPECT_METRIC_EQ(
1965       1, metrics::NumEvents("WebRTC.Video.Encoded.Qp.Vp9.S1", kQpIdx1));
1966 }
1967 
TEST_F(SendStatisticsProxyTest,VerifyQpHistogramStats_Vp9OneSpatialLayer)1968 TEST_F(SendStatisticsProxyTest, VerifyQpHistogramStats_Vp9OneSpatialLayer) {
1969   test::ScopedKeyValueConfig field_trials;
1970   VideoSendStream::Config config(nullptr);
1971   config.rtp.ssrcs.push_back(kFirstSsrc);
1972   statistics_proxy_.reset(new SendStatisticsProxy(
1973       &fake_clock_, config, VideoEncoderConfig::ContentType::kRealtimeVideo,
1974       field_trials));
1975 
1976   EncodedImage encoded_image;
1977   CodecSpecificInfo codec_info;
1978   codec_info.codecType = kVideoCodecVP9;
1979   codec_info.codecSpecific.VP9.num_spatial_layers = 1;
1980 
1981   for (int i = 0; i < SendStatisticsProxy::kMinRequiredMetricsSamples; ++i) {
1982     encoded_image.qp_ = kQpIdx0;
1983     statistics_proxy_->OnSendEncodedImage(encoded_image, &codec_info);
1984   }
1985   statistics_proxy_.reset();
1986   EXPECT_METRIC_EQ(1, metrics::NumSamples("WebRTC.Video.Encoded.Qp.Vp9"));
1987   EXPECT_METRIC_EQ(1,
1988                    metrics::NumEvents("WebRTC.Video.Encoded.Qp.Vp9", kQpIdx0));
1989 }
1990 
TEST_F(SendStatisticsProxyTest,VerifyQpHistogramStats_H264)1991 TEST_F(SendStatisticsProxyTest, VerifyQpHistogramStats_H264) {
1992   EncodedImage encoded_image;
1993   CodecSpecificInfo codec_info;
1994   codec_info.codecType = kVideoCodecH264;
1995 
1996   for (int i = 0; i < SendStatisticsProxy::kMinRequiredMetricsSamples; ++i) {
1997     encoded_image.SetSpatialIndex(0);
1998     encoded_image.qp_ = kQpIdx0;
1999     statistics_proxy_->OnSendEncodedImage(encoded_image, &codec_info);
2000     encoded_image.SetSpatialIndex(1);
2001     encoded_image.qp_ = kQpIdx1;
2002     statistics_proxy_->OnSendEncodedImage(encoded_image, &codec_info);
2003   }
2004   statistics_proxy_.reset();
2005   EXPECT_METRIC_EQ(1, metrics::NumSamples("WebRTC.Video.Encoded.Qp.H264.S0"));
2006   EXPECT_METRIC_EQ(
2007       1, metrics::NumEvents("WebRTC.Video.Encoded.Qp.H264.S0", kQpIdx0));
2008   EXPECT_METRIC_EQ(1, metrics::NumSamples("WebRTC.Video.Encoded.Qp.H264.S1"));
2009   EXPECT_METRIC_EQ(
2010       1, metrics::NumEvents("WebRTC.Video.Encoded.Qp.H264.S1", kQpIdx1));
2011 }
2012 
TEST_F(SendStatisticsProxyTest,BandwidthLimitedHistogramsNotUpdatedForOneStream)2013 TEST_F(SendStatisticsProxyTest,
2014        BandwidthLimitedHistogramsNotUpdatedForOneStream) {
2015   // Configure one stream.
2016   VideoEncoderConfig config;
2017   config.content_type = VideoEncoderConfig::ContentType::kRealtimeVideo;
2018   VideoStream stream1;
2019   stream1.width = kWidth;
2020   stream1.height = kHeight;
2021   statistics_proxy_->OnEncoderReconfigured(config, {stream1});
2022 
2023   const int64_t kMaxEncodedFrameWindowMs = 800;
2024   const int kFps = 20;
2025   const int kNumFramesPerWindow = kFps * kMaxEncodedFrameWindowMs / 1000;
2026   const int kMinSamples =  // Sample added when removed from EncodedFrameMap.
2027       SendStatisticsProxy::kMinRequiredMetricsSamples + kNumFramesPerWindow;
2028 
2029   // Stream encoded.
2030   EncodedImage encoded_image;
2031   encoded_image._encodedWidth = kWidth;
2032   encoded_image._encodedHeight = kHeight;
2033   for (int i = 0; i < kMinSamples; ++i) {
2034     fake_clock_.AdvanceTimeMilliseconds(1000 / kFps);
2035     encoded_image.SetTimestamp(encoded_image.Timestamp() +
2036                                (kRtpClockRateHz / kFps));
2037     statistics_proxy_->OnSendEncodedImage(encoded_image, nullptr);
2038   }
2039 
2040   // Histograms are updated when the statistics_proxy_ is deleted.
2041   statistics_proxy_.reset();
2042   EXPECT_METRIC_EQ(0, metrics::NumSamples(
2043                           "WebRTC.Video.BandwidthLimitedResolutionInPercent"));
2044   EXPECT_METRIC_EQ(0, metrics::NumSamples(
2045                           "WebRTC.Video.BandwidthLimitedResolutionsDisabled"));
2046 }
2047 
TEST_F(SendStatisticsProxyTest,BandwidthLimitedHistogramsUpdatedForTwoStreams_NoResolutionDisabled)2048 TEST_F(SendStatisticsProxyTest,
2049        BandwidthLimitedHistogramsUpdatedForTwoStreams_NoResolutionDisabled) {
2050   // Configure two streams.
2051   VideoEncoderConfig config;
2052   config.content_type = VideoEncoderConfig::ContentType::kRealtimeVideo;
2053   VideoStream stream1;
2054   stream1.width = kWidth / 2;
2055   stream1.height = kHeight / 2;
2056   VideoStream stream2;
2057   stream2.width = kWidth;
2058   stream2.height = kHeight;
2059   statistics_proxy_->OnEncoderReconfigured(config, {stream1, stream2});
2060 
2061   const int64_t kMaxEncodedFrameWindowMs = 800;
2062   const int kFps = 20;
2063   const int kNumFramesPerWindow = kFps * kMaxEncodedFrameWindowMs / 1000;
2064   const int kMinSamples =  // Sample added when removed from EncodedFrameMap.
2065       SendStatisticsProxy::kMinRequiredMetricsSamples + kNumFramesPerWindow;
2066 
2067   // Two streams encoded.
2068   EncodedImage encoded_image;
2069   for (int i = 0; i < kMinSamples; ++i) {
2070     fake_clock_.AdvanceTimeMilliseconds(1000 / kFps);
2071     encoded_image.SetTimestamp(encoded_image.Timestamp() +
2072                                (kRtpClockRateHz / kFps));
2073     encoded_image._encodedWidth = kWidth;
2074     encoded_image._encodedHeight = kHeight;
2075     statistics_proxy_->OnSendEncodedImage(encoded_image, nullptr);
2076     encoded_image._encodedWidth = kWidth / 2;
2077     encoded_image._encodedHeight = kHeight / 2;
2078     statistics_proxy_->OnSendEncodedImage(encoded_image, nullptr);
2079   }
2080 
2081   // Histograms are updated when the statistics_proxy_ is deleted.
2082   statistics_proxy_.reset();
2083   EXPECT_METRIC_EQ(1, metrics::NumSamples(
2084                           "WebRTC.Video.BandwidthLimitedResolutionInPercent"));
2085   EXPECT_METRIC_EQ(
2086       1, metrics::NumEvents("WebRTC.Video.BandwidthLimitedResolutionInPercent",
2087                             0));
2088   // No resolution disabled.
2089   EXPECT_METRIC_EQ(0, metrics::NumSamples(
2090                           "WebRTC.Video.BandwidthLimitedResolutionsDisabled"));
2091 }
2092 
TEST_F(SendStatisticsProxyTest,BandwidthLimitedHistogramsUpdatedForTwoStreams_OneResolutionDisabled)2093 TEST_F(SendStatisticsProxyTest,
2094        BandwidthLimitedHistogramsUpdatedForTwoStreams_OneResolutionDisabled) {
2095   // Configure two streams.
2096   VideoEncoderConfig config;
2097   config.content_type = VideoEncoderConfig::ContentType::kRealtimeVideo;
2098   VideoStream stream1;
2099   stream1.width = kWidth / 2;
2100   stream1.height = kHeight / 2;
2101   VideoStream stream2;
2102   stream2.width = kWidth;
2103   stream2.height = kHeight;
2104   statistics_proxy_->OnEncoderReconfigured(config, {stream1, stream2});
2105 
2106   const int64_t kMaxEncodedFrameWindowMs = 800;
2107   const int kFps = 20;
2108   const int kNumFramesPerWindow = kFps * kMaxEncodedFrameWindowMs / 1000;
2109   const int kMinSamples =  // Sample added when removed from EncodedFrameMap.
2110       SendStatisticsProxy::kMinRequiredMetricsSamples + kNumFramesPerWindow;
2111 
2112   // One stream encoded.
2113   EncodedImage encoded_image;
2114   encoded_image._encodedWidth = kWidth / 2;
2115   encoded_image._encodedHeight = kHeight / 2;
2116   for (int i = 0; i < kMinSamples; ++i) {
2117     fake_clock_.AdvanceTimeMilliseconds(1000 / kFps);
2118     encoded_image.SetTimestamp(encoded_image.Timestamp() +
2119                                (kRtpClockRateHz / kFps));
2120     statistics_proxy_->OnSendEncodedImage(encoded_image, nullptr);
2121   }
2122 
2123   // Histograms are updated when the statistics_proxy_ is deleted.
2124   statistics_proxy_.reset();
2125   EXPECT_METRIC_EQ(1, metrics::NumSamples(
2126                           "WebRTC.Video.BandwidthLimitedResolutionInPercent"));
2127   EXPECT_METRIC_EQ(
2128       1, metrics::NumEvents("WebRTC.Video.BandwidthLimitedResolutionInPercent",
2129                             100));
2130   // One resolution disabled.
2131   EXPECT_METRIC_EQ(1, metrics::NumSamples(
2132                           "WebRTC.Video.BandwidthLimitedResolutionsDisabled"));
2133   EXPECT_METRIC_EQ(
2134       1, metrics::NumEvents("WebRTC.Video.BandwidthLimitedResolutionsDisabled",
2135                             1));
2136 }
2137 
TEST_F(SendStatisticsProxyTest,QualityLimitedHistogramsNotUpdatedWhenDisabled)2138 TEST_F(SendStatisticsProxyTest,
2139        QualityLimitedHistogramsNotUpdatedWhenDisabled) {
2140   statistics_proxy_->UpdateAdaptationSettings(kFramerateScalingDisabled,
2141                                               kScalingDisabled);
2142   EncodedImage encoded_image;
2143   encoded_image.SetSpatialIndex(0);
2144   for (int i = 0; i < SendStatisticsProxy::kMinRequiredMetricsSamples; ++i)
2145     statistics_proxy_->OnSendEncodedImage(encoded_image, &kDefaultCodecInfo);
2146 
2147   // Histograms are updated when the statistics_proxy_ is deleted.
2148   statistics_proxy_.reset();
2149   EXPECT_METRIC_EQ(
2150       0, metrics::NumSamples("WebRTC.Video.QualityLimitedResolutionInPercent"));
2151   EXPECT_METRIC_EQ(0, metrics::NumSamples(
2152                           "WebRTC.Video.QualityLimitedResolutionDownscales"));
2153 }
2154 
TEST_F(SendStatisticsProxyTest,QualityLimitedHistogramsUpdatedWhenEnabled_NoResolutionDownscale)2155 TEST_F(SendStatisticsProxyTest,
2156        QualityLimitedHistogramsUpdatedWhenEnabled_NoResolutionDownscale) {
2157   statistics_proxy_->UpdateAdaptationSettings(kScalingEnabled, kScalingEnabled);
2158   EncodedImage encoded_image;
2159   encoded_image.SetSpatialIndex(0);
2160   for (int i = 0; i < SendStatisticsProxy::kMinRequiredMetricsSamples; ++i)
2161     statistics_proxy_->OnSendEncodedImage(encoded_image, &kDefaultCodecInfo);
2162 
2163   // Histograms are updated when the statistics_proxy_ is deleted.
2164   statistics_proxy_.reset();
2165   EXPECT_METRIC_EQ(
2166       1, metrics::NumSamples("WebRTC.Video.QualityLimitedResolutionInPercent"));
2167   EXPECT_METRIC_EQ(1, metrics::NumEvents(
2168                           "WebRTC.Video.QualityLimitedResolutionInPercent", 0));
2169   // No resolution downscale.
2170   EXPECT_METRIC_EQ(0, metrics::NumSamples(
2171                           "WebRTC.Video.QualityLimitedResolutionDownscales"));
2172 }
2173 
TEST_F(SendStatisticsProxyTest,QualityLimitedHistogramsUpdatedWhenEnabled_TwoResolutionDownscales)2174 TEST_F(SendStatisticsProxyTest,
2175        QualityLimitedHistogramsUpdatedWhenEnabled_TwoResolutionDownscales) {
2176   const int kDownscales = 2;
2177   VideoAdaptationCounters cpu_counts;
2178   VideoAdaptationCounters quality_counts;
2179   quality_counts.resolution_adaptations = kDownscales;
2180   statistics_proxy_->UpdateAdaptationSettings(kScalingEnabled, kScalingEnabled);
2181   statistics_proxy_->OnAdaptationChanged(VideoAdaptationReason::kQuality,
2182                                          cpu_counts, quality_counts);
2183   EncodedImage encoded_image;
2184   encoded_image.SetSpatialIndex(0);
2185   for (int i = 0; i < SendStatisticsProxy::kMinRequiredMetricsSamples; ++i)
2186     statistics_proxy_->OnSendEncodedImage(encoded_image, &kDefaultCodecInfo);
2187   // Histograms are updated when the statistics_proxy_ is deleted.
2188   statistics_proxy_.reset();
2189   EXPECT_METRIC_EQ(
2190       1, metrics::NumSamples("WebRTC.Video.QualityLimitedResolutionInPercent"));
2191   EXPECT_METRIC_EQ(
2192       1, metrics::NumEvents("WebRTC.Video.QualityLimitedResolutionInPercent",
2193                             100));
2194   // Resolution downscales.
2195   EXPECT_METRIC_EQ(1, metrics::NumSamples(
2196                           "WebRTC.Video.QualityLimitedResolutionDownscales"));
2197   EXPECT_METRIC_EQ(
2198       1, metrics::NumEvents("WebRTC.Video.QualityLimitedResolutionDownscales",
2199                             kDownscales));
2200 }
2201 
TEST_F(SendStatisticsProxyTest,GetStatsReportsBandwidthLimitedResolution)2202 TEST_F(SendStatisticsProxyTest, GetStatsReportsBandwidthLimitedResolution) {
2203   // Initially false.
2204   EXPECT_FALSE(statistics_proxy_->GetStats().bw_limited_resolution);
2205 
2206   // Configure two streams.
2207   VideoEncoderConfig config;
2208   config.content_type = VideoEncoderConfig::ContentType::kRealtimeVideo;
2209   config.number_of_streams = 2;
2210   VideoStream stream1;
2211   stream1.width = kWidth / 2;
2212   stream1.height = kHeight / 2;
2213   VideoStream stream2;
2214   stream2.width = kWidth;
2215   stream2.height = kHeight;
2216   statistics_proxy_->OnEncoderReconfigured(config, {stream1, stream2});
2217 
2218   // One stream encoded.
2219   EncodedImage encoded_image;
2220   encoded_image._encodedWidth = kWidth / 2;
2221   encoded_image._encodedHeight = kHeight / 2;
2222 
2223   // Resolution scaled due to quality.
2224   VideoAdaptationCounters cpu_counts;
2225   VideoAdaptationCounters quality_counts;
2226   quality_counts.resolution_adaptations = 1;
2227   statistics_proxy_->UpdateAdaptationSettings(kFramerateScalingDisabled,
2228                                               kFramerateScalingDisabled);
2229   statistics_proxy_->OnAdaptationChanged(VideoAdaptationReason::kQuality,
2230                                          cpu_counts, quality_counts);
2231   statistics_proxy_->OnSendEncodedImage(encoded_image, nullptr);
2232   EXPECT_TRUE(statistics_proxy_->GetStats().bw_limited_resolution);
2233 
2234   // Adapt up.
2235   quality_counts.resolution_adaptations = 0;
2236   statistics_proxy_->OnAdaptationChanged(VideoAdaptationReason::kQuality,
2237                                          cpu_counts, quality_counts);
2238   statistics_proxy_->OnSendEncodedImage(encoded_image, nullptr);
2239   EXPECT_FALSE(statistics_proxy_->GetStats().bw_limited_resolution);
2240 
2241   // Bw disabled one layer.
2242   VideoCodec codec;
2243   codec.numberOfSimulcastStreams = 2;
2244   codec.simulcastStream[0].active = true;
2245   codec.simulcastStream[1].active = true;
2246   VideoBitrateAllocation allocation;
2247   // Some positive bitrate only on the second stream.
2248   allocation.SetBitrate(1, 0, 10000);
2249   allocation.set_bw_limited(true);
2250   statistics_proxy_->OnBitrateAllocationUpdated(codec, allocation);
2251   EXPECT_TRUE(statistics_proxy_->GetStats().bw_limited_resolution);
2252 
2253   // Revert for the next test.
2254   allocation.set_bw_limited(false);
2255   statistics_proxy_->OnBitrateAllocationUpdated(codec, allocation);
2256   EXPECT_FALSE(statistics_proxy_->GetStats().bw_limited_resolution);
2257 
2258   // Internal encoder scaler reduced resolution.
2259   statistics_proxy_->OnEncoderInternalScalerUpdate(/*scaled=*/true);
2260   EXPECT_TRUE(statistics_proxy_->GetStats().bw_limited_resolution);
2261 }
2262 
TEST_F(SendStatisticsProxyTest,GetStatsReportsTargetMediaBitrate)2263 TEST_F(SendStatisticsProxyTest, GetStatsReportsTargetMediaBitrate) {
2264   // Initially zero.
2265   EXPECT_EQ(0, statistics_proxy_->GetStats().target_media_bitrate_bps);
2266 
2267   const int kBitrate = 100000;
2268   statistics_proxy_->OnSetEncoderTargetRate(kBitrate);
2269   EXPECT_EQ(kBitrate, statistics_proxy_->GetStats().target_media_bitrate_bps);
2270 
2271   statistics_proxy_->OnSetEncoderTargetRate(0);
2272   EXPECT_EQ(0, statistics_proxy_->GetStats().target_media_bitrate_bps);
2273 }
2274 
TEST_F(SendStatisticsProxyTest,NoSubstreams)2275 TEST_F(SendStatisticsProxyTest, NoSubstreams) {
2276   uint32_t excluded_ssrc =
2277       std::max(*absl::c_max_element(config_.rtp.ssrcs),
2278                *absl::c_max_element(config_.rtp.rtx.ssrcs)) +
2279       1;
2280   // From ReportBlockDataObserver.
2281   ReportBlockDataObserver* rtcp_callback = statistics_proxy_.get();
2282   RTCPReportBlock report_block;
2283   report_block.source_ssrc = excluded_ssrc;
2284   ReportBlockData data;
2285   data.SetReportBlock(report_block, 0);
2286   rtcp_callback->OnReportBlockDataUpdated(data);
2287 
2288   // From BitrateStatisticsObserver.
2289   uint32_t total = 0;
2290   uint32_t retransmit = 0;
2291   BitrateStatisticsObserver* bitrate_observer = statistics_proxy_.get();
2292   bitrate_observer->Notify(total, retransmit, excluded_ssrc);
2293 
2294   // From FrameCountObserver.
2295   FrameCountObserver* fps_observer = statistics_proxy_.get();
2296   FrameCounts frame_counts;
2297   frame_counts.key_frames = 1;
2298   fps_observer->FrameCountUpdated(frame_counts, excluded_ssrc);
2299 
2300   VideoSendStream::Stats stats = statistics_proxy_->GetStats();
2301   EXPECT_TRUE(stats.substreams.empty());
2302 }
2303 
TEST_F(SendStatisticsProxyTest,EncodedResolutionTimesOut)2304 TEST_F(SendStatisticsProxyTest, EncodedResolutionTimesOut) {
2305   static const int kEncodedWidth = 123;
2306   static const int kEncodedHeight = 81;
2307   EncodedImage encoded_image;
2308   encoded_image._encodedWidth = kEncodedWidth;
2309   encoded_image._encodedHeight = kEncodedHeight;
2310   encoded_image.SetSpatialIndex(0);
2311 
2312   CodecSpecificInfo codec_info;
2313   codec_info.codecType = kVideoCodecVP8;
2314 
2315   statistics_proxy_->OnSendEncodedImage(encoded_image, &codec_info);
2316   encoded_image.SetSpatialIndex(1);
2317   statistics_proxy_->OnSendEncodedImage(encoded_image, &codec_info);
2318 
2319   VideoSendStream::Stats stats = statistics_proxy_->GetStats();
2320   EXPECT_EQ(kEncodedWidth, stats.substreams[config_.rtp.ssrcs[0]].width);
2321   EXPECT_EQ(kEncodedHeight, stats.substreams[config_.rtp.ssrcs[0]].height);
2322   EXPECT_EQ(kEncodedWidth, stats.substreams[config_.rtp.ssrcs[1]].width);
2323   EXPECT_EQ(kEncodedHeight, stats.substreams[config_.rtp.ssrcs[1]].height);
2324 
2325   // Forward almost to timeout, this should not have removed stats.
2326   fake_clock_.AdvanceTimeMilliseconds(SendStatisticsProxy::kStatsTimeoutMs - 1);
2327   stats = statistics_proxy_->GetStats();
2328   EXPECT_EQ(kEncodedWidth, stats.substreams[config_.rtp.ssrcs[0]].width);
2329   EXPECT_EQ(kEncodedHeight, stats.substreams[config_.rtp.ssrcs[0]].height);
2330 
2331   // Update the first SSRC with bogus RTCP stats to make sure that encoded
2332   // resolution still times out (no global timeout for all stats).
2333   ReportBlockDataObserver* rtcp_callback = statistics_proxy_.get();
2334   RTCPReportBlock report_block;
2335   report_block.source_ssrc = config_.rtp.ssrcs[0];
2336   ReportBlockData data;
2337   data.SetReportBlock(report_block, 0);
2338   rtcp_callback->OnReportBlockDataUpdated(data);
2339 
2340   // Report stats for second SSRC to make sure it's not outdated along with the
2341   // first SSRC.
2342   statistics_proxy_->OnSendEncodedImage(encoded_image, &codec_info);
2343 
2344   // Forward 1 ms, reach timeout, substream 0 should have no resolution
2345   // reported, but substream 1 should.
2346   fake_clock_.AdvanceTimeMilliseconds(1);
2347   stats = statistics_proxy_->GetStats();
2348   EXPECT_EQ(0, stats.substreams[config_.rtp.ssrcs[0]].width);
2349   EXPECT_EQ(0, stats.substreams[config_.rtp.ssrcs[0]].height);
2350   EXPECT_EQ(kEncodedWidth, stats.substreams[config_.rtp.ssrcs[1]].width);
2351   EXPECT_EQ(kEncodedHeight, stats.substreams[config_.rtp.ssrcs[1]].height);
2352 }
2353 
TEST_F(SendStatisticsProxyTest,ClearsResolutionFromInactiveSsrcs)2354 TEST_F(SendStatisticsProxyTest, ClearsResolutionFromInactiveSsrcs) {
2355   static const int kEncodedWidth = 123;
2356   static const int kEncodedHeight = 81;
2357   EncodedImage encoded_image;
2358   encoded_image._encodedWidth = kEncodedWidth;
2359   encoded_image._encodedHeight = kEncodedHeight;
2360   encoded_image.SetSpatialIndex(0);
2361 
2362   CodecSpecificInfo codec_info;
2363   codec_info.codecType = kVideoCodecVP8;
2364 
2365   statistics_proxy_->OnSendEncodedImage(encoded_image, &codec_info);
2366   encoded_image.SetSpatialIndex(1);
2367   statistics_proxy_->OnSendEncodedImage(encoded_image, &codec_info);
2368 
2369   statistics_proxy_->OnInactiveSsrc(config_.rtp.ssrcs[1]);
2370   VideoSendStream::Stats stats = statistics_proxy_->GetStats();
2371   EXPECT_EQ(kEncodedWidth, stats.substreams[config_.rtp.ssrcs[0]].width);
2372   EXPECT_EQ(kEncodedHeight, stats.substreams[config_.rtp.ssrcs[0]].height);
2373   EXPECT_EQ(0, stats.substreams[config_.rtp.ssrcs[1]].width);
2374   EXPECT_EQ(0, stats.substreams[config_.rtp.ssrcs[1]].height);
2375 }
2376 
TEST_F(SendStatisticsProxyTest,ClearsBitratesFromInactiveSsrcs)2377 TEST_F(SendStatisticsProxyTest, ClearsBitratesFromInactiveSsrcs) {
2378   uint32_t bitrate = 42;
2379   BitrateStatisticsObserver* observer = statistics_proxy_.get();
2380   observer->Notify(bitrate, bitrate, config_.rtp.ssrcs[0]);
2381   observer->Notify(bitrate, bitrate, config_.rtp.ssrcs[1]);
2382 
2383   statistics_proxy_->OnInactiveSsrc(config_.rtp.ssrcs[1]);
2384 
2385   VideoSendStream::Stats stats = statistics_proxy_->GetStats();
2386   EXPECT_EQ(static_cast<int>(bitrate),
2387             stats.substreams[config_.rtp.ssrcs[0]].total_bitrate_bps);
2388   EXPECT_EQ(static_cast<int>(bitrate),
2389             stats.substreams[config_.rtp.ssrcs[0]].retransmit_bitrate_bps);
2390   EXPECT_EQ(0, stats.substreams[config_.rtp.ssrcs[1]].total_bitrate_bps);
2391   EXPECT_EQ(0, stats.substreams[config_.rtp.ssrcs[1]].retransmit_bitrate_bps);
2392 }
2393 
TEST_F(SendStatisticsProxyTest,ResetsRtcpCountersOnContentChange)2394 TEST_F(SendStatisticsProxyTest, ResetsRtcpCountersOnContentChange) {
2395   RtcpPacketTypeCounterObserver* proxy =
2396       static_cast<RtcpPacketTypeCounterObserver*>(statistics_proxy_.get());
2397   RtcpPacketTypeCounter counters;
2398   proxy->RtcpPacketTypesCounterUpdated(kFirstSsrc, counters);
2399   proxy->RtcpPacketTypesCounterUpdated(kSecondSsrc, counters);
2400 
2401   fake_clock_.AdvanceTimeMilliseconds(1000 * metrics::kMinRunTimeInSeconds);
2402 
2403   counters.nack_packets += 1 * metrics::kMinRunTimeInSeconds;
2404   counters.fir_packets += 2 * metrics::kMinRunTimeInSeconds;
2405   counters.pli_packets += 3 * metrics::kMinRunTimeInSeconds;
2406   counters.unique_nack_requests += 4 * metrics::kMinRunTimeInSeconds;
2407   counters.nack_requests += 5 * metrics::kMinRunTimeInSeconds;
2408 
2409   proxy->RtcpPacketTypesCounterUpdated(kFirstSsrc, counters);
2410   proxy->RtcpPacketTypesCounterUpdated(kSecondSsrc, counters);
2411 
2412   // Changing content type causes histograms to be reported.
2413   VideoEncoderConfig config;
2414   config.content_type = VideoEncoderConfig::ContentType::kScreen;
2415   statistics_proxy_->OnEncoderReconfigured(config, {});
2416 
2417   EXPECT_METRIC_EQ(
2418       1, metrics::NumSamples("WebRTC.Video.NackPacketsReceivedPerMinute"));
2419   EXPECT_METRIC_EQ(
2420       1, metrics::NumSamples("WebRTC.Video.FirPacketsReceivedPerMinute"));
2421   EXPECT_METRIC_EQ(
2422       1, metrics::NumSamples("WebRTC.Video.PliPacketsReceivedPerMinute"));
2423   EXPECT_METRIC_EQ(1, metrics::NumSamples(
2424                           "WebRTC.Video.UniqueNackRequestsReceivedInPercent"));
2425 
2426   const int kRate = 60 * 2;  // Packets per minute with two streams.
2427 
2428   EXPECT_METRIC_EQ(
2429       1, metrics::NumEvents("WebRTC.Video.NackPacketsReceivedPerMinute",
2430                             1 * kRate));
2431   EXPECT_METRIC_EQ(
2432       1, metrics::NumEvents("WebRTC.Video.FirPacketsReceivedPerMinute",
2433                             2 * kRate));
2434   EXPECT_METRIC_EQ(
2435       1, metrics::NumEvents("WebRTC.Video.PliPacketsReceivedPerMinute",
2436                             3 * kRate));
2437   EXPECT_METRIC_EQ(
2438       1, metrics::NumEvents("WebRTC.Video.UniqueNackRequestsReceivedInPercent",
2439                             4 * 100 / 5));
2440 
2441   // New start time but same counter values.
2442   proxy->RtcpPacketTypesCounterUpdated(kFirstSsrc, counters);
2443   proxy->RtcpPacketTypesCounterUpdated(kSecondSsrc, counters);
2444 
2445   fake_clock_.AdvanceTimeMilliseconds(1000 * metrics::kMinRunTimeInSeconds);
2446 
2447   counters.nack_packets += 1 * metrics::kMinRunTimeInSeconds;
2448   counters.fir_packets += 2 * metrics::kMinRunTimeInSeconds;
2449   counters.pli_packets += 3 * metrics::kMinRunTimeInSeconds;
2450   counters.unique_nack_requests += 4 * metrics::kMinRunTimeInSeconds;
2451   counters.nack_requests += 5 * metrics::kMinRunTimeInSeconds;
2452 
2453   proxy->RtcpPacketTypesCounterUpdated(kFirstSsrc, counters);
2454   proxy->RtcpPacketTypesCounterUpdated(kSecondSsrc, counters);
2455 
2456   SetUp();  // Reset stats proxy also causes histograms to be reported.
2457 
2458   EXPECT_METRIC_EQ(
2459       1, metrics::NumSamples(
2460              "WebRTC.Video.Screenshare.NackPacketsReceivedPerMinute"));
2461   EXPECT_METRIC_EQ(1,
2462                    metrics::NumSamples(
2463                        "WebRTC.Video.Screenshare.FirPacketsReceivedPerMinute"));
2464   EXPECT_METRIC_EQ(1,
2465                    metrics::NumSamples(
2466                        "WebRTC.Video.Screenshare.PliPacketsReceivedPerMinute"));
2467   EXPECT_METRIC_EQ(
2468       1, metrics::NumSamples(
2469              "WebRTC.Video.Screenshare.UniqueNackRequestsReceivedInPercent"));
2470 
2471   EXPECT_METRIC_EQ(
2472       1,
2473       metrics::NumEvents(
2474           "WebRTC.Video.Screenshare.NackPacketsReceivedPerMinute", 1 * kRate));
2475   EXPECT_METRIC_EQ(
2476       1,
2477       metrics::NumEvents("WebRTC.Video.Screenshare.FirPacketsReceivedPerMinute",
2478                          2 * kRate));
2479   EXPECT_METRIC_EQ(
2480       1,
2481       metrics::NumEvents("WebRTC.Video.Screenshare.PliPacketsReceivedPerMinute",
2482                          3 * kRate));
2483   EXPECT_METRIC_EQ(
2484       1, metrics::NumEvents(
2485              "WebRTC.Video.Screenshare.UniqueNackRequestsReceivedInPercent",
2486              4 * 100 / 5));
2487 }
2488 
TEST_F(SendStatisticsProxyTest,GetStatsReportsIsRtx)2489 TEST_F(SendStatisticsProxyTest, GetStatsReportsIsRtx) {
2490   StreamDataCountersCallback* proxy =
2491       static_cast<StreamDataCountersCallback*>(statistics_proxy_.get());
2492   StreamDataCounters counters;
2493   proxy->DataCountersUpdated(counters, kFirstSsrc);
2494   proxy->DataCountersUpdated(counters, kFirstRtxSsrc);
2495 
2496   EXPECT_NE(GetStreamStats(kFirstSsrc).type,
2497             VideoSendStream::StreamStats::StreamType::kRtx);
2498   EXPECT_EQ(GetStreamStats(kFirstSsrc).referenced_media_ssrc, absl::nullopt);
2499   EXPECT_EQ(GetStreamStats(kFirstRtxSsrc).type,
2500             VideoSendStream::StreamStats::StreamType::kRtx);
2501   EXPECT_EQ(GetStreamStats(kFirstRtxSsrc).referenced_media_ssrc, kFirstSsrc);
2502 }
2503 
TEST_F(SendStatisticsProxyTest,GetStatsReportsIsFlexFec)2504 TEST_F(SendStatisticsProxyTest, GetStatsReportsIsFlexFec) {
2505   test::ScopedKeyValueConfig field_trials;
2506   statistics_proxy_.reset(new SendStatisticsProxy(
2507       &fake_clock_, GetTestConfigWithFlexFec(),
2508       VideoEncoderConfig::ContentType::kRealtimeVideo, field_trials));
2509 
2510   StreamDataCountersCallback* proxy =
2511       static_cast<StreamDataCountersCallback*>(statistics_proxy_.get());
2512   StreamDataCounters counters;
2513   proxy->DataCountersUpdated(counters, kFirstSsrc);
2514   proxy->DataCountersUpdated(counters, kFlexFecSsrc);
2515 
2516   EXPECT_NE(GetStreamStats(kFirstSsrc).type,
2517             VideoSendStream::StreamStats::StreamType::kFlexfec);
2518   EXPECT_EQ(GetStreamStats(kFirstSsrc).referenced_media_ssrc, absl::nullopt);
2519   EXPECT_EQ(GetStreamStats(kFlexFecSsrc).type,
2520             VideoSendStream::StreamStats::StreamType::kFlexfec);
2521   EXPECT_EQ(GetStreamStats(kFlexFecSsrc).referenced_media_ssrc, kFirstSsrc);
2522 }
2523 
TEST_F(SendStatisticsProxyTest,SendBitratesAreReportedWithFlexFecEnabled)2524 TEST_F(SendStatisticsProxyTest, SendBitratesAreReportedWithFlexFecEnabled) {
2525   test::ScopedKeyValueConfig field_trials;
2526   statistics_proxy_.reset(new SendStatisticsProxy(
2527       &fake_clock_, GetTestConfigWithFlexFec(),
2528       VideoEncoderConfig::ContentType::kRealtimeVideo, field_trials));
2529 
2530   StreamDataCountersCallback* proxy =
2531       static_cast<StreamDataCountersCallback*>(statistics_proxy_.get());
2532   StreamDataCounters counters;
2533   StreamDataCounters rtx_counters;
2534 
2535   const int kMinRequiredPeriodSamples = 8;
2536   const int kPeriodIntervalMs = 2000;
2537   for (int i = 0; i < kMinRequiredPeriodSamples; ++i) {
2538     counters.transmitted.packets += 20;
2539     counters.transmitted.header_bytes += 500;
2540     counters.transmitted.padding_bytes += 1000;
2541     counters.transmitted.payload_bytes += 2000;
2542     counters.retransmitted.packets += 2;
2543     counters.retransmitted.header_bytes += 25;
2544     counters.retransmitted.padding_bytes += 100;
2545     counters.retransmitted.payload_bytes += 250;
2546     counters.fec = counters.retransmitted;
2547     rtx_counters.transmitted = counters.transmitted;
2548     // Advance one interval and update counters.
2549     fake_clock_.AdvanceTimeMilliseconds(kPeriodIntervalMs);
2550     proxy->DataCountersUpdated(counters, kFirstSsrc);
2551     proxy->DataCountersUpdated(counters, kSecondSsrc);
2552     proxy->DataCountersUpdated(rtx_counters, kFirstRtxSsrc);
2553     proxy->DataCountersUpdated(rtx_counters, kSecondRtxSsrc);
2554     proxy->DataCountersUpdated(counters, kFlexFecSsrc);
2555   }
2556 
2557   statistics_proxy_.reset();
2558   // Interval: 3500 bytes * 4 / 2 sec = 7000 bytes / sec  = 56 kbps
2559   EXPECT_METRIC_EQ(1, metrics::NumSamples("WebRTC.Video.BitrateSentInKbps"));
2560   EXPECT_METRIC_EQ(1, metrics::NumEvents("WebRTC.Video.BitrateSentInKbps", 56));
2561   // Interval: 3500 bytes * 2 / 2 sec = 3500 bytes / sec  = 28 kbps
2562   EXPECT_METRIC_EQ(1, metrics::NumSamples("WebRTC.Video.RtxBitrateSentInKbps"));
2563   EXPECT_METRIC_EQ(1,
2564                    metrics::NumEvents("WebRTC.Video.RtxBitrateSentInKbps", 28));
2565   // Interval: (2000 - 2 * 250) bytes / 2 sec = 1500 bytes / sec  = 12 kbps
2566   EXPECT_METRIC_EQ(1,
2567                    metrics::NumSamples("WebRTC.Video.MediaBitrateSentInKbps"));
2568   EXPECT_METRIC_EQ(
2569       1, metrics::NumEvents("WebRTC.Video.MediaBitrateSentInKbps", 12));
2570   // Interval: 1000 bytes * 4 / 2 sec = 2000 bytes / sec = 16 kbps
2571   EXPECT_METRIC_EQ(
2572       1, metrics::NumSamples("WebRTC.Video.PaddingBitrateSentInKbps"));
2573   EXPECT_METRIC_EQ(
2574       1, metrics::NumEvents("WebRTC.Video.PaddingBitrateSentInKbps", 16));
2575   // Interval: 375 bytes * 2 / 2 sec = 375 bytes / sec = 3 kbps
2576   EXPECT_METRIC_EQ(1, metrics::NumSamples("WebRTC.Video.FecBitrateSentInKbps"));
2577   EXPECT_METRIC_EQ(1,
2578                    metrics::NumEvents("WebRTC.Video.FecBitrateSentInKbps", 3));
2579   // Interval: 375 bytes * 2 / 2 sec = 375 bytes / sec = 3 kbps
2580   EXPECT_METRIC_EQ(
2581       1, metrics::NumSamples("WebRTC.Video.RetransmittedBitrateSentInKbps"));
2582   EXPECT_METRIC_EQ(
2583       1, metrics::NumEvents("WebRTC.Video.RetransmittedBitrateSentInKbps", 3));
2584 }
2585 
TEST_F(SendStatisticsProxyTest,ResetsRtpCountersOnContentChange)2586 TEST_F(SendStatisticsProxyTest, ResetsRtpCountersOnContentChange) {
2587   StreamDataCountersCallback* proxy =
2588       static_cast<StreamDataCountersCallback*>(statistics_proxy_.get());
2589   StreamDataCounters counters;
2590   StreamDataCounters rtx_counters;
2591   counters.first_packet_time_ms = fake_clock_.TimeInMilliseconds();
2592 
2593   const int kMinRequiredPeriodSamples = 8;
2594   const int kPeriodIntervalMs = 2000;
2595   for (int i = 0; i < kMinRequiredPeriodSamples; ++i) {
2596     counters.transmitted.packets += 20;
2597     counters.transmitted.header_bytes += 500;
2598     counters.transmitted.padding_bytes += 1000;
2599     counters.transmitted.payload_bytes += 2000;
2600     counters.retransmitted.packets += 2;
2601     counters.retransmitted.header_bytes += 25;
2602     counters.retransmitted.padding_bytes += 100;
2603     counters.retransmitted.payload_bytes += 250;
2604     counters.fec = counters.retransmitted;
2605     rtx_counters.transmitted = counters.transmitted;
2606     // Advance one interval and update counters.
2607     fake_clock_.AdvanceTimeMilliseconds(kPeriodIntervalMs);
2608     proxy->DataCountersUpdated(counters, kFirstSsrc);
2609     proxy->DataCountersUpdated(counters, kSecondSsrc);
2610     proxy->DataCountersUpdated(rtx_counters, kFirstRtxSsrc);
2611     proxy->DataCountersUpdated(rtx_counters, kSecondRtxSsrc);
2612   }
2613 
2614   // Changing content type causes histograms to be reported.
2615   VideoEncoderConfig config;
2616   config.content_type = VideoEncoderConfig::ContentType::kScreen;
2617   statistics_proxy_->OnEncoderReconfigured(config, {});
2618 
2619   // Interval: 3500 bytes * 4 / 2 sec = 7000 bytes / sec  = 56 kbps
2620   EXPECT_METRIC_EQ(1, metrics::NumSamples("WebRTC.Video.BitrateSentInKbps"));
2621   EXPECT_METRIC_EQ(1, metrics::NumEvents("WebRTC.Video.BitrateSentInKbps", 56));
2622   // Interval: 3500 bytes * 2 / 2 sec = 3500 bytes / sec  = 28 kbps
2623   EXPECT_METRIC_EQ(1, metrics::NumSamples("WebRTC.Video.RtxBitrateSentInKbps"));
2624   EXPECT_METRIC_EQ(1,
2625                    metrics::NumEvents("WebRTC.Video.RtxBitrateSentInKbps", 28));
2626   // Interval: (2000 - 2 * 250) bytes / 2 sec = 1500 bytes / sec  = 12 kbps
2627   EXPECT_METRIC_EQ(1,
2628                    metrics::NumSamples("WebRTC.Video.MediaBitrateSentInKbps"));
2629   EXPECT_METRIC_EQ(
2630       1, metrics::NumEvents("WebRTC.Video.MediaBitrateSentInKbps", 12));
2631   // Interval: 1000 bytes * 4 / 2 sec = 2000 bytes / sec = 16 kbps
2632   EXPECT_METRIC_EQ(
2633       1, metrics::NumSamples("WebRTC.Video.PaddingBitrateSentInKbps"));
2634   EXPECT_METRIC_EQ(
2635       1, metrics::NumEvents("WebRTC.Video.PaddingBitrateSentInKbps", 16));
2636   // Interval: 375 bytes * 2 / 2 sec = 375 bytes / sec = 3 kbps
2637   EXPECT_METRIC_EQ(1, metrics::NumSamples("WebRTC.Video.FecBitrateSentInKbps"));
2638   EXPECT_METRIC_EQ(1,
2639                    metrics::NumEvents("WebRTC.Video.FecBitrateSentInKbps", 3));
2640   // Interval: 375 bytes * 2 / 2 sec = 375 bytes / sec = 3 kbps
2641   EXPECT_METRIC_EQ(
2642       1, metrics::NumSamples("WebRTC.Video.RetransmittedBitrateSentInKbps"));
2643   EXPECT_METRIC_EQ(
2644       1, metrics::NumEvents("WebRTC.Video.RetransmittedBitrateSentInKbps", 3));
2645 
2646   // New metric counters but same data counters.
2647   // Double counter values, this should result in the same counts as before but
2648   // with new histogram names.
2649   for (int i = 0; i < kMinRequiredPeriodSamples; ++i) {
2650     counters.transmitted.packets += 20;
2651     counters.transmitted.header_bytes += 500;
2652     counters.transmitted.padding_bytes += 1000;
2653     counters.transmitted.payload_bytes += 2000;
2654     counters.retransmitted.packets += 2;
2655     counters.retransmitted.header_bytes += 25;
2656     counters.retransmitted.padding_bytes += 100;
2657     counters.retransmitted.payload_bytes += 250;
2658     counters.fec = counters.retransmitted;
2659     rtx_counters.transmitted = counters.transmitted;
2660     // Advance one interval and update counters.
2661     fake_clock_.AdvanceTimeMilliseconds(kPeriodIntervalMs);
2662     proxy->DataCountersUpdated(counters, kFirstSsrc);
2663     proxy->DataCountersUpdated(counters, kSecondSsrc);
2664     proxy->DataCountersUpdated(rtx_counters, kFirstRtxSsrc);
2665     proxy->DataCountersUpdated(rtx_counters, kSecondRtxSsrc);
2666   }
2667 
2668   // Reset stats proxy also causes histograms to be reported.
2669   statistics_proxy_.reset();
2670 
2671   // Interval: 3500 bytes * 4 / 2 sec = 7000 bytes / sec  = 56 kbps
2672   EXPECT_METRIC_EQ(
2673       1, metrics::NumSamples("WebRTC.Video.Screenshare.BitrateSentInKbps"));
2674   EXPECT_METRIC_EQ(
2675       1, metrics::NumEvents("WebRTC.Video.Screenshare.BitrateSentInKbps", 56));
2676   // Interval: 3500 bytes * 2 / 2 sec = 3500 bytes / sec  = 28 kbps
2677   EXPECT_METRIC_EQ(
2678       1, metrics::NumSamples("WebRTC.Video.Screenshare.RtxBitrateSentInKbps"));
2679   EXPECT_METRIC_EQ(1, metrics::NumEvents(
2680                           "WebRTC.Video.Screenshare.RtxBitrateSentInKbps", 28));
2681   // Interval: (2000 - 2 * 250) bytes / 2 sec = 1500 bytes / sec  = 12 kbps
2682   EXPECT_METRIC_EQ(1, metrics::NumSamples(
2683                           "WebRTC.Video.Screenshare.MediaBitrateSentInKbps"));
2684   EXPECT_METRIC_EQ(
2685       1, metrics::NumEvents("WebRTC.Video.Screenshare.MediaBitrateSentInKbps",
2686                             12));
2687   // Interval: 1000 bytes * 4 / 2 sec = 2000 bytes / sec = 16 kbps
2688   EXPECT_METRIC_EQ(1, metrics::NumSamples(
2689                           "WebRTC.Video.Screenshare.PaddingBitrateSentInKbps"));
2690   EXPECT_METRIC_EQ(
2691       1, metrics::NumEvents("WebRTC.Video.Screenshare.PaddingBitrateSentInKbps",
2692                             16));
2693   // Interval: 375 bytes * 2 / 2 sec = 375 bytes / sec = 3 kbps
2694   EXPECT_METRIC_EQ(
2695       1, metrics::NumSamples("WebRTC.Video.Screenshare.FecBitrateSentInKbps"));
2696   EXPECT_METRIC_EQ(1, metrics::NumEvents(
2697                           "WebRTC.Video.Screenshare.FecBitrateSentInKbps", 3));
2698   // Interval: 375 bytes * 2 / 2 sec = 375 bytes / sec = 3 kbps
2699   EXPECT_METRIC_EQ(
2700       1, metrics::NumSamples(
2701              "WebRTC.Video.Screenshare.RetransmittedBitrateSentInKbps"));
2702   EXPECT_METRIC_EQ(
2703       1, metrics::NumEvents(
2704              "WebRTC.Video.Screenshare.RetransmittedBitrateSentInKbps", 3));
2705 }
2706 
TEST_F(SendStatisticsProxyTest,RtxBitrateIsZeroWhenEnabledAndNoRtxDataIsSent)2707 TEST_F(SendStatisticsProxyTest, RtxBitrateIsZeroWhenEnabledAndNoRtxDataIsSent) {
2708   StreamDataCountersCallback* proxy =
2709       static_cast<StreamDataCountersCallback*>(statistics_proxy_.get());
2710   StreamDataCounters counters;
2711   StreamDataCounters rtx_counters;
2712 
2713   const int kMinRequiredPeriodSamples = 8;
2714   const int kPeriodIntervalMs = 2000;
2715   for (int i = 0; i < kMinRequiredPeriodSamples; ++i) {
2716     counters.transmitted.packets += 20;
2717     counters.transmitted.header_bytes += 500;
2718     counters.transmitted.payload_bytes += 2000;
2719     counters.fec = counters.retransmitted;
2720     // Advance one interval and update counters.
2721     fake_clock_.AdvanceTimeMilliseconds(kPeriodIntervalMs);
2722     proxy->DataCountersUpdated(counters, kFirstSsrc);
2723   }
2724 
2725   // RTX enabled. No data sent over RTX.
2726   statistics_proxy_.reset();
2727   EXPECT_METRIC_EQ(1, metrics::NumSamples("WebRTC.Video.RtxBitrateSentInKbps"));
2728   EXPECT_METRIC_EQ(1,
2729                    metrics::NumEvents("WebRTC.Video.RtxBitrateSentInKbps", 0));
2730 }
2731 
TEST_F(SendStatisticsProxyTest,RtxBitrateNotReportedWhenNotEnabled)2732 TEST_F(SendStatisticsProxyTest, RtxBitrateNotReportedWhenNotEnabled) {
2733   test::ScopedKeyValueConfig field_trials;
2734   VideoSendStream::Config config(nullptr);
2735   config.rtp.ssrcs.push_back(kFirstSsrc);  // RTX not configured.
2736   statistics_proxy_.reset(new SendStatisticsProxy(
2737       &fake_clock_, config, VideoEncoderConfig::ContentType::kRealtimeVideo,
2738       field_trials));
2739 
2740   StreamDataCountersCallback* proxy =
2741       static_cast<StreamDataCountersCallback*>(statistics_proxy_.get());
2742   StreamDataCounters counters;
2743 
2744   const int kMinRequiredPeriodSamples = 8;
2745   const int kPeriodIntervalMs = 2000;
2746   for (int i = 0; i < kMinRequiredPeriodSamples; ++i) {
2747     counters.transmitted.packets += 20;
2748     counters.transmitted.header_bytes += 500;
2749     counters.transmitted.payload_bytes += 2000;
2750     counters.fec = counters.retransmitted;
2751     // Advance one interval and update counters.
2752     fake_clock_.AdvanceTimeMilliseconds(kPeriodIntervalMs);
2753     proxy->DataCountersUpdated(counters, kFirstSsrc);
2754   }
2755 
2756   // RTX not enabled.
2757   statistics_proxy_.reset();
2758   EXPECT_METRIC_EQ(0, metrics::NumSamples("WebRTC.Video.RtxBitrateSentInKbps"));
2759 }
2760 
TEST_F(SendStatisticsProxyTest,FecBitrateIsZeroWhenEnabledAndNoFecDataIsSent)2761 TEST_F(SendStatisticsProxyTest, FecBitrateIsZeroWhenEnabledAndNoFecDataIsSent) {
2762   StreamDataCountersCallback* proxy =
2763       static_cast<StreamDataCountersCallback*>(statistics_proxy_.get());
2764   StreamDataCounters counters;
2765   StreamDataCounters rtx_counters;
2766 
2767   const int kMinRequiredPeriodSamples = 8;
2768   const int kPeriodIntervalMs = 2000;
2769   for (int i = 0; i < kMinRequiredPeriodSamples; ++i) {
2770     counters.transmitted.packets += 20;
2771     counters.transmitted.header_bytes += 500;
2772     counters.transmitted.payload_bytes += 2000;
2773     // Advance one interval and update counters.
2774     fake_clock_.AdvanceTimeMilliseconds(kPeriodIntervalMs);
2775     proxy->DataCountersUpdated(counters, kFirstSsrc);
2776   }
2777 
2778   // FEC enabled. No FEC data sent.
2779   statistics_proxy_.reset();
2780   EXPECT_METRIC_EQ(1, metrics::NumSamples("WebRTC.Video.FecBitrateSentInKbps"));
2781   EXPECT_METRIC_EQ(1,
2782                    metrics::NumEvents("WebRTC.Video.FecBitrateSentInKbps", 0));
2783 }
2784 
TEST_F(SendStatisticsProxyTest,FecBitrateNotReportedWhenNotEnabled)2785 TEST_F(SendStatisticsProxyTest, FecBitrateNotReportedWhenNotEnabled) {
2786   test::ScopedKeyValueConfig field_trials;
2787   VideoSendStream::Config config(nullptr);
2788   config.rtp.ssrcs.push_back(kFirstSsrc);  // FEC not configured.
2789   statistics_proxy_.reset(new SendStatisticsProxy(
2790       &fake_clock_, config, VideoEncoderConfig::ContentType::kRealtimeVideo,
2791       field_trials));
2792 
2793   StreamDataCountersCallback* proxy =
2794       static_cast<StreamDataCountersCallback*>(statistics_proxy_.get());
2795   StreamDataCounters counters;
2796 
2797   const int kMinRequiredPeriodSamples = 8;
2798   const int kPeriodIntervalMs = 2000;
2799   for (int i = 0; i < kMinRequiredPeriodSamples; ++i) {
2800     counters.transmitted.packets += 20;
2801     counters.transmitted.header_bytes += 500;
2802     counters.transmitted.payload_bytes += 2000;
2803     counters.fec = counters.retransmitted;
2804     // Advance one interval and update counters.
2805     fake_clock_.AdvanceTimeMilliseconds(kPeriodIntervalMs);
2806     proxy->DataCountersUpdated(counters, kFirstSsrc);
2807   }
2808 
2809   // FEC not enabled.
2810   statistics_proxy_.reset();
2811   EXPECT_METRIC_EQ(0, metrics::NumSamples("WebRTC.Video.FecBitrateSentInKbps"));
2812 }
2813 
TEST_F(SendStatisticsProxyTest,GetStatsReportsEncoderImplementationName)2814 TEST_F(SendStatisticsProxyTest, GetStatsReportsEncoderImplementationName) {
2815   const std::string kName = "encoderName";
2816   statistics_proxy_->OnEncoderImplementationChanged(EncoderImplementation{
2817       .name = kName,
2818       .is_hardware_accelerated = true,
2819   });
2820   EXPECT_EQ(kName, statistics_proxy_->GetStats().encoder_implementation_name);
2821   EXPECT_THAT(statistics_proxy_->GetStats().power_efficient_encoder,
2822               ::testing::IsTrue());
2823 }
2824 
TEST_F(SendStatisticsProxyTest,Vp9SvcLowSpatialLayerDoesNotUpdateResolution)2825 TEST_F(SendStatisticsProxyTest, Vp9SvcLowSpatialLayerDoesNotUpdateResolution) {
2826   static const int kEncodedWidth = 123;
2827   static const int kEncodedHeight = 81;
2828   EncodedImage encoded_image;
2829   encoded_image._encodedWidth = kEncodedWidth;
2830   encoded_image._encodedHeight = kEncodedHeight;
2831   encoded_image.SetSpatialIndex(0);
2832 
2833   CodecSpecificInfo codec_info;
2834   codec_info.codecType = kVideoCodecVP9;
2835 
2836   // For first picture, it is expected that low layer updates resolution.
2837   codec_info.end_of_picture = false;
2838   statistics_proxy_->OnSendEncodedImage(encoded_image, &codec_info);
2839   VideoSendStream::Stats stats = statistics_proxy_->GetStats();
2840   EXPECT_EQ(kEncodedWidth, stats.substreams[config_.rtp.ssrcs[0]].width);
2841   EXPECT_EQ(kEncodedHeight, stats.substreams[config_.rtp.ssrcs[0]].height);
2842 
2843   // Top layer updates resolution.
2844   encoded_image._encodedWidth = kEncodedWidth * 2;
2845   encoded_image._encodedHeight = kEncodedHeight * 2;
2846   codec_info.end_of_picture = true;
2847   statistics_proxy_->OnSendEncodedImage(encoded_image, &codec_info);
2848   stats = statistics_proxy_->GetStats();
2849   EXPECT_EQ(kEncodedWidth * 2, stats.substreams[config_.rtp.ssrcs[0]].width);
2850   EXPECT_EQ(kEncodedHeight * 2, stats.substreams[config_.rtp.ssrcs[0]].height);
2851 
2852   // Low layer of next frame doesn't update resolution.
2853   encoded_image._encodedWidth = kEncodedWidth;
2854   encoded_image._encodedHeight = kEncodedHeight;
2855   codec_info.end_of_picture = false;
2856   statistics_proxy_->OnSendEncodedImage(encoded_image, &codec_info);
2857   stats = statistics_proxy_->GetStats();
2858   EXPECT_EQ(kEncodedWidth * 2, stats.substreams[config_.rtp.ssrcs[0]].width);
2859   EXPECT_EQ(kEncodedHeight * 2, stats.substreams[config_.rtp.ssrcs[0]].height);
2860 }
2861 
2862 class ForcedFallbackTest : public SendStatisticsProxyTest {
2863  public:
ForcedFallbackTest(const std::string & field_trials)2864   explicit ForcedFallbackTest(const std::string& field_trials)
2865       : SendStatisticsProxyTest(field_trials) {
2866     codec_info_.codecType = kVideoCodecVP8;
2867     codec_info_.codecSpecific.VP8.temporalIdx = 0;
2868     encoded_image_._encodedWidth = kWidth;
2869     encoded_image_._encodedHeight = kHeight;
2870     encoded_image_.SetSpatialIndex(0);
2871   }
2872 
~ForcedFallbackTest()2873   ~ForcedFallbackTest() override {}
2874 
2875  protected:
InsertEncodedFrames(int num_frames,int interval_ms)2876   void InsertEncodedFrames(int num_frames, int interval_ms) {
2877     statistics_proxy_->OnEncoderImplementationChanged(
2878         {.name = codec_name_, .is_hardware_accelerated = false});
2879 
2880     // First frame is not updating stats, insert initial frame.
2881     if (statistics_proxy_->GetStats().frames_encoded == 0) {
2882       statistics_proxy_->OnSendEncodedImage(encoded_image_, &codec_info_);
2883     }
2884     for (int i = 0; i < num_frames; ++i) {
2885       statistics_proxy_->OnSendEncodedImage(encoded_image_, &codec_info_);
2886       fake_clock_.AdvanceTimeMilliseconds(interval_ms);
2887     }
2888     // Add frame to include last time interval.
2889     statistics_proxy_->OnSendEncodedImage(encoded_image_, &codec_info_);
2890   }
2891 
2892   EncodedImage encoded_image_;
2893   CodecSpecificInfo codec_info_;
2894   std::string codec_name_;
2895   const std::string kPrefix = "WebRTC.Video.Encoder.ForcedSw";
2896   const int kFrameIntervalMs = 1000;
2897   const int kMinFrames = 20;  // Min run time 20 sec.
2898 };
2899 
2900 class ForcedFallbackDisabled : public ForcedFallbackTest {
2901  public:
ForcedFallbackDisabled()2902   ForcedFallbackDisabled()
2903       : ForcedFallbackTest("WebRTC-VP8-Forced-Fallback-Encoder-v2/Disabled-1," +
2904                            std::to_string(kWidth * kHeight) + ",3/") {}
2905 };
2906 
2907 class ForcedFallbackEnabled : public ForcedFallbackTest {
2908  public:
ForcedFallbackEnabled()2909   ForcedFallbackEnabled()
2910       : ForcedFallbackTest("WebRTC-VP8-Forced-Fallback-Encoder-v2/Enabled-1," +
2911                            std::to_string(kWidth * kHeight) + ",3/") {}
2912 };
2913 
TEST_F(ForcedFallbackEnabled,StatsNotUpdatedIfMinRunTimeHasNotPassed)2914 TEST_F(ForcedFallbackEnabled, StatsNotUpdatedIfMinRunTimeHasNotPassed) {
2915   InsertEncodedFrames(kMinFrames, kFrameIntervalMs - 1);
2916   statistics_proxy_.reset();
2917   EXPECT_METRIC_EQ(0,
2918                    metrics::NumSamples(kPrefix + "FallbackTimeInPercent.Vp8"));
2919   EXPECT_METRIC_EQ(
2920       0, metrics::NumSamples(kPrefix + "FallbackChangesPerMinute.Vp8"));
2921 }
2922 
TEST_F(ForcedFallbackEnabled,StatsUpdated)2923 TEST_F(ForcedFallbackEnabled, StatsUpdated) {
2924   InsertEncodedFrames(kMinFrames, kFrameIntervalMs);
2925   EXPECT_FALSE(statistics_proxy_->GetStats().has_entered_low_resolution);
2926   statistics_proxy_.reset();
2927   EXPECT_METRIC_EQ(1,
2928                    metrics::NumSamples(kPrefix + "FallbackTimeInPercent.Vp8"));
2929   EXPECT_METRIC_EQ(
2930       1, metrics::NumEvents(kPrefix + "FallbackTimeInPercent.Vp8", 0));
2931   EXPECT_METRIC_EQ(
2932       1, metrics::NumSamples(kPrefix + "FallbackChangesPerMinute.Vp8"));
2933   EXPECT_METRIC_EQ(
2934       1, metrics::NumEvents(kPrefix + "FallbackChangesPerMinute.Vp8", 0));
2935 }
2936 
TEST_F(ForcedFallbackEnabled,StatsNotUpdatedIfNotVp8)2937 TEST_F(ForcedFallbackEnabled, StatsNotUpdatedIfNotVp8) {
2938   codec_info_.codecType = kVideoCodecVP9;
2939   InsertEncodedFrames(kMinFrames, kFrameIntervalMs);
2940   statistics_proxy_.reset();
2941   EXPECT_METRIC_EQ(0,
2942                    metrics::NumSamples(kPrefix + "FallbackTimeInPercent.Vp8"));
2943   EXPECT_METRIC_EQ(
2944       0, metrics::NumSamples(kPrefix + "FallbackChangesPerMinute.Vp8"));
2945 }
2946 
TEST_F(ForcedFallbackEnabled,StatsNotUpdatedForTemporalLayers)2947 TEST_F(ForcedFallbackEnabled, StatsNotUpdatedForTemporalLayers) {
2948   codec_info_.codecSpecific.VP8.temporalIdx = 1;
2949   InsertEncodedFrames(kMinFrames, kFrameIntervalMs);
2950   statistics_proxy_.reset();
2951   EXPECT_METRIC_EQ(0,
2952                    metrics::NumSamples(kPrefix + "FallbackTimeInPercent.Vp8"));
2953   EXPECT_METRIC_EQ(
2954       0, metrics::NumSamples(kPrefix + "FallbackChangesPerMinute.Vp8"));
2955 }
2956 
TEST_F(ForcedFallbackEnabled,StatsNotUpdatedForSimulcast)2957 TEST_F(ForcedFallbackEnabled, StatsNotUpdatedForSimulcast) {
2958   encoded_image_.SetSpatialIndex(1);
2959   InsertEncodedFrames(kMinFrames, kFrameIntervalMs);
2960   statistics_proxy_.reset();
2961   EXPECT_METRIC_EQ(0,
2962                    metrics::NumSamples(kPrefix + "FallbackTimeInPercent.Vp8"));
2963   EXPECT_METRIC_EQ(
2964       0, metrics::NumSamples(kPrefix + "FallbackChangesPerMinute.Vp8"));
2965 }
2966 
TEST_F(ForcedFallbackDisabled,StatsNotUpdatedIfNoFieldTrial)2967 TEST_F(ForcedFallbackDisabled, StatsNotUpdatedIfNoFieldTrial) {
2968   InsertEncodedFrames(kMinFrames, kFrameIntervalMs);
2969   statistics_proxy_.reset();
2970   EXPECT_METRIC_EQ(0,
2971                    metrics::NumSamples(kPrefix + "FallbackTimeInPercent.Vp8"));
2972   EXPECT_METRIC_EQ(
2973       0, metrics::NumSamples(kPrefix + "FallbackChangesPerMinute.Vp8"));
2974 }
2975 
TEST_F(ForcedFallbackDisabled,EnteredLowResolutionSetIfAtMaxPixels)2976 TEST_F(ForcedFallbackDisabled, EnteredLowResolutionSetIfAtMaxPixels) {
2977   InsertEncodedFrames(1, kFrameIntervalMs);
2978   EXPECT_TRUE(statistics_proxy_->GetStats().has_entered_low_resolution);
2979 }
2980 
TEST_F(ForcedFallbackEnabled,EnteredLowResolutionNotSetIfNotLibvpx)2981 TEST_F(ForcedFallbackEnabled, EnteredLowResolutionNotSetIfNotLibvpx) {
2982   InsertEncodedFrames(1, kFrameIntervalMs);
2983   EXPECT_FALSE(statistics_proxy_->GetStats().has_entered_low_resolution);
2984 }
2985 
TEST_F(ForcedFallbackEnabled,EnteredLowResolutionSetIfLibvpx)2986 TEST_F(ForcedFallbackEnabled, EnteredLowResolutionSetIfLibvpx) {
2987   codec_name_ = "libvpx";
2988   InsertEncodedFrames(1, kFrameIntervalMs);
2989   EXPECT_TRUE(statistics_proxy_->GetStats().has_entered_low_resolution);
2990 }
2991 
TEST_F(ForcedFallbackDisabled,EnteredLowResolutionNotSetIfAboveMaxPixels)2992 TEST_F(ForcedFallbackDisabled, EnteredLowResolutionNotSetIfAboveMaxPixels) {
2993   encoded_image_._encodedWidth = kWidth + 1;
2994   InsertEncodedFrames(1, kFrameIntervalMs);
2995   EXPECT_FALSE(statistics_proxy_->GetStats().has_entered_low_resolution);
2996 }
2997 
TEST_F(ForcedFallbackDisabled,EnteredLowResolutionNotSetIfLibvpx)2998 TEST_F(ForcedFallbackDisabled, EnteredLowResolutionNotSetIfLibvpx) {
2999   codec_name_ = "libvpx";
3000   InsertEncodedFrames(1, kFrameIntervalMs);
3001   EXPECT_FALSE(statistics_proxy_->GetStats().has_entered_low_resolution);
3002 }
3003 
TEST_F(ForcedFallbackDisabled,EnteredLowResolutionSetIfOnMinPixelLimitReached)3004 TEST_F(ForcedFallbackDisabled,
3005        EnteredLowResolutionSetIfOnMinPixelLimitReached) {
3006   encoded_image_._encodedWidth = kWidth + 1;
3007   statistics_proxy_->OnMinPixelLimitReached();
3008   InsertEncodedFrames(1, kFrameIntervalMs);
3009   EXPECT_TRUE(statistics_proxy_->GetStats().has_entered_low_resolution);
3010 }
3011 
TEST_F(ForcedFallbackEnabled,OneFallbackEvent)3012 TEST_F(ForcedFallbackEnabled, OneFallbackEvent) {
3013   // One change. Video: 20000 ms, fallback: 5000 ms (25%).
3014   EXPECT_FALSE(statistics_proxy_->GetStats().has_entered_low_resolution);
3015   InsertEncodedFrames(15, 1000);
3016   EXPECT_FALSE(statistics_proxy_->GetStats().has_entered_low_resolution);
3017   codec_name_ = "libvpx";
3018   InsertEncodedFrames(5, 1000);
3019   EXPECT_TRUE(statistics_proxy_->GetStats().has_entered_low_resolution);
3020 
3021   statistics_proxy_.reset();
3022   EXPECT_METRIC_EQ(1,
3023                    metrics::NumSamples(kPrefix + "FallbackTimeInPercent.Vp8"));
3024   EXPECT_METRIC_EQ(
3025       1, metrics::NumEvents(kPrefix + "FallbackTimeInPercent.Vp8", 25));
3026   EXPECT_METRIC_EQ(
3027       1, metrics::NumSamples(kPrefix + "FallbackChangesPerMinute.Vp8"));
3028   EXPECT_METRIC_EQ(
3029       1, metrics::NumEvents(kPrefix + "FallbackChangesPerMinute.Vp8", 3));
3030 }
3031 
TEST_F(ForcedFallbackEnabled,ThreeFallbackEvents)3032 TEST_F(ForcedFallbackEnabled, ThreeFallbackEvents) {
3033   codec_info_.codecSpecific.VP8.temporalIdx = kNoTemporalIdx;  // Should work.
3034   const int kMaxFrameDiffMs = 2000;
3035 
3036   // Three changes. Video: 60000 ms, fallback: 15000 ms (25%).
3037   InsertEncodedFrames(10, 1000);
3038   EXPECT_FALSE(statistics_proxy_->GetStats().has_entered_low_resolution);
3039   codec_name_ = "libvpx";
3040   InsertEncodedFrames(15, 500);
3041   EXPECT_TRUE(statistics_proxy_->GetStats().has_entered_low_resolution);
3042   codec_name_ = "notlibvpx";
3043   InsertEncodedFrames(20, 1000);
3044   InsertEncodedFrames(3, kMaxFrameDiffMs);  // Should not be included.
3045   InsertEncodedFrames(10, 1000);
3046   EXPECT_TRUE(statistics_proxy_->GetStats().has_entered_low_resolution);
3047   codec_name_ = "notlibvpx2";
3048   InsertEncodedFrames(10, 500);
3049   EXPECT_TRUE(statistics_proxy_->GetStats().has_entered_low_resolution);
3050   codec_name_ = "libvpx";
3051   InsertEncodedFrames(15, 500);
3052   EXPECT_TRUE(statistics_proxy_->GetStats().has_entered_low_resolution);
3053 
3054   statistics_proxy_.reset();
3055   EXPECT_METRIC_EQ(1,
3056                    metrics::NumSamples(kPrefix + "FallbackTimeInPercent.Vp8"));
3057   EXPECT_METRIC_EQ(
3058       1, metrics::NumEvents(kPrefix + "FallbackTimeInPercent.Vp8", 25));
3059   EXPECT_METRIC_EQ(
3060       1, metrics::NumSamples(kPrefix + "FallbackChangesPerMinute.Vp8"));
3061   EXPECT_METRIC_EQ(
3062       1, metrics::NumEvents(kPrefix + "FallbackChangesPerMinute.Vp8", 3));
3063 }
3064 
TEST_F(ForcedFallbackEnabled,NoFallbackIfAboveMaxPixels)3065 TEST_F(ForcedFallbackEnabled, NoFallbackIfAboveMaxPixels) {
3066   encoded_image_._encodedWidth = kWidth + 1;
3067   codec_name_ = "libvpx";
3068   InsertEncodedFrames(kMinFrames, kFrameIntervalMs);
3069 
3070   EXPECT_FALSE(statistics_proxy_->GetStats().has_entered_low_resolution);
3071   statistics_proxy_.reset();
3072   EXPECT_METRIC_EQ(0,
3073                    metrics::NumSamples(kPrefix + "FallbackTimeInPercent.Vp8"));
3074   EXPECT_METRIC_EQ(
3075       0, metrics::NumSamples(kPrefix + "FallbackChangesPerMinute.Vp8"));
3076 }
3077 
TEST_F(ForcedFallbackEnabled,FallbackIfAtMaxPixels)3078 TEST_F(ForcedFallbackEnabled, FallbackIfAtMaxPixels) {
3079   encoded_image_._encodedWidth = kWidth;
3080   codec_name_ = "libvpx";
3081   InsertEncodedFrames(kMinFrames, kFrameIntervalMs);
3082 
3083   EXPECT_TRUE(statistics_proxy_->GetStats().has_entered_low_resolution);
3084   statistics_proxy_.reset();
3085   EXPECT_METRIC_EQ(1,
3086                    metrics::NumSamples(kPrefix + "FallbackTimeInPercent.Vp8"));
3087   EXPECT_METRIC_EQ(
3088       1, metrics::NumSamples(kPrefix + "FallbackChangesPerMinute.Vp8"));
3089 }
3090 
3091 }  // namespace webrtc
3092