• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  *  Copyright 2018 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 "absl/types/optional.h"
12 #include "api/test/video/function_video_encoder_factory.h"
13 #include "modules/video_coding/codecs/vp8/include/vp8.h"
14 #include "rtc_base/synchronization/mutex.h"
15 #include "system_wrappers/include/metrics.h"
16 #include "test/call_test.h"
17 #include "test/gtest.h"
18 
19 namespace webrtc {
20 namespace {
21 enum : int {  // The first valid value is 1.
22   kTransportSequenceNumberExtensionId = 1,
23   kVideoContentTypeExtensionId,
24 };
25 }  // namespace
26 
27 class HistogramTest : public test::CallTest {
28  public:
HistogramTest()29   HistogramTest() {
30     RegisterRtpExtension(RtpExtension(RtpExtension::kTransportSequenceNumberUri,
31                                       kTransportSequenceNumberExtensionId));
32     RegisterRtpExtension(RtpExtension(RtpExtension::kVideoContentTypeUri,
33                                       kVideoContentTypeExtensionId));
34   }
35 
36  protected:
37   void VerifyHistogramStats(bool use_rtx, bool use_fec, bool screenshare);
38 };
39 
VerifyHistogramStats(bool use_rtx,bool use_fec,bool screenshare)40 void HistogramTest::VerifyHistogramStats(bool use_rtx,
41                                          bool use_fec,
42                                          bool screenshare) {
43   class FrameObserver : public test::EndToEndTest,
44                         public rtc::VideoSinkInterface<VideoFrame> {
45    public:
46     FrameObserver(bool use_rtx, bool use_fec, bool screenshare)
47         : EndToEndTest(kLongTimeout),
48           use_rtx_(use_rtx),
49           use_fec_(use_fec),
50           screenshare_(screenshare),
51           // This test uses NACK, so to send FEC we can't use a fake encoder.
52           encoder_factory_([]() { return VP8Encoder::Create(); }),
53           num_frames_received_(0) {}
54 
55    private:
56     void OnFrame(const VideoFrame& video_frame) override {
57       // The RTT is needed to estimate `ntp_time_ms` which is used by
58       // end-to-end delay stats. Therefore, start counting received frames once
59       // `ntp_time_ms` is valid.
60       if (video_frame.ntp_time_ms() > 0 &&
61           Clock::GetRealTimeClock()->CurrentNtpInMilliseconds() >=
62               video_frame.ntp_time_ms()) {
63         MutexLock lock(&mutex_);
64         ++num_frames_received_;
65       }
66     }
67 
68     Action OnSendRtp(const uint8_t* packet, size_t length) override {
69       if (MinMetricRunTimePassed() && MinNumberOfFramesReceived())
70         observation_complete_.Set();
71 
72       return SEND_PACKET;
73     }
74 
75     bool MinMetricRunTimePassed() {
76       int64_t now_ms = Clock::GetRealTimeClock()->TimeInMilliseconds();
77       if (!start_runtime_ms_)
78         start_runtime_ms_ = now_ms;
79 
80       int64_t elapsed_sec = (now_ms - *start_runtime_ms_) / 1000;
81       return elapsed_sec > metrics::kMinRunTimeInSeconds * 2;
82     }
83 
84     bool MinNumberOfFramesReceived() const {
85       const int kMinRequiredHistogramSamples = 200;
86       MutexLock lock(&mutex_);
87       return num_frames_received_ > kMinRequiredHistogramSamples;
88     }
89 
90     void ModifyVideoConfigs(
91         VideoSendStream::Config* send_config,
92         std::vector<VideoReceiveStreamInterface::Config>* receive_configs,
93         VideoEncoderConfig* encoder_config) override {
94       // NACK
95       send_config->rtp.nack.rtp_history_ms = kNackRtpHistoryMs;
96       (*receive_configs)[0].rtp.nack.rtp_history_ms = kNackRtpHistoryMs;
97       (*receive_configs)[0].renderer = this;
98       // FEC
99       if (use_fec_) {
100         send_config->rtp.ulpfec.ulpfec_payload_type = kUlpfecPayloadType;
101         send_config->rtp.ulpfec.red_payload_type = kRedPayloadType;
102         send_config->encoder_settings.encoder_factory = &encoder_factory_;
103         send_config->rtp.payload_name = "VP8";
104         encoder_config->codec_type = kVideoCodecVP8;
105         (*receive_configs)[0].decoders[0].video_format = SdpVideoFormat("VP8");
106         (*receive_configs)[0].rtp.red_payload_type = kRedPayloadType;
107         (*receive_configs)[0].rtp.ulpfec_payload_type = kUlpfecPayloadType;
108       }
109       // RTX
110       if (use_rtx_) {
111         send_config->rtp.rtx.ssrcs.push_back(kSendRtxSsrcs[0]);
112         send_config->rtp.rtx.payload_type = kSendRtxPayloadType;
113         (*receive_configs)[0].rtp.rtx_ssrc = kSendRtxSsrcs[0];
114         (*receive_configs)[0]
115             .rtp.rtx_associated_payload_types[kSendRtxPayloadType] =
116             kFakeVideoSendPayloadType;
117         if (use_fec_) {
118           send_config->rtp.ulpfec.red_rtx_payload_type = kRtxRedPayloadType;
119           (*receive_configs)[0]
120               .rtp.rtx_associated_payload_types[kRtxRedPayloadType] =
121               kSendRtxPayloadType;
122         }
123       }
124       // RTT needed for RemoteNtpTimeEstimator for the receive stream.
125       (*receive_configs)[0].rtp.rtcp_xr.receiver_reference_time_report = true;
126       encoder_config->content_type =
127           screenshare_ ? VideoEncoderConfig::ContentType::kScreen
128                        : VideoEncoderConfig::ContentType::kRealtimeVideo;
129     }
130 
131     void PerformTest() override {
132       EXPECT_TRUE(Wait()) << "Timed out waiting for min frames to be received.";
133     }
134 
135     mutable Mutex mutex_;
136     const bool use_rtx_;
137     const bool use_fec_;
138     const bool screenshare_;
139     test::FunctionVideoEncoderFactory encoder_factory_;
140     absl::optional<int64_t> start_runtime_ms_;
141     int num_frames_received_ RTC_GUARDED_BY(&mutex_);
142   } test(use_rtx, use_fec, screenshare);
143 
144   metrics::Reset();
145   RunBaseTest(&test);
146 
147   const std::string video_prefix =
148       screenshare ? "WebRTC.Video.Screenshare." : "WebRTC.Video.";
149   // The content type extension is disabled in non screenshare test,
150   // therefore no slicing on simulcast id should be present.
151   const std::string video_suffix = screenshare ? ".S0" : "";
152 
153   // Verify that stats have been updated once.
154   EXPECT_METRIC_EQ(2, metrics::NumSamples("WebRTC.Call.LifetimeInSeconds"));
155   EXPECT_METRIC_EQ(1, metrics::NumSamples(
156                           "WebRTC.Call.TimeReceivingVideoRtpPacketsInSeconds"));
157   EXPECT_METRIC_EQ(
158       1, metrics::NumSamples("WebRTC.Call.VideoBitrateReceivedInKbps"));
159   EXPECT_METRIC_EQ(1,
160                    metrics::NumSamples("WebRTC.Call.RtcpBitrateReceivedInBps"));
161   EXPECT_METRIC_EQ(1, metrics::NumSamples("WebRTC.Call.BitrateReceivedInKbps"));
162   EXPECT_METRIC_EQ(
163       1, metrics::NumSamples("WebRTC.Call.EstimatedSendBitrateInKbps"));
164   EXPECT_METRIC_EQ(1, metrics::NumSamples("WebRTC.Call.PacerBitrateInKbps"));
165 
166   EXPECT_METRIC_EQ(
167       1, metrics::NumSamples("WebRTC.Video.SendStreamLifetimeInSeconds"));
168   EXPECT_METRIC_EQ(
169       1, metrics::NumSamples("WebRTC.Video.ReceiveStreamLifetimeInSeconds"));
170 
171   EXPECT_METRIC_EQ(
172       1, metrics::NumSamples("WebRTC.Video.NackPacketsSentPerMinute"));
173   EXPECT_METRIC_EQ(
174       1, metrics::NumSamples(video_prefix + "NackPacketsReceivedPerMinute"));
175   EXPECT_METRIC_EQ(1,
176                    metrics::NumSamples("WebRTC.Video.FirPacketsSentPerMinute"));
177   EXPECT_METRIC_EQ(
178       1, metrics::NumSamples(video_prefix + "FirPacketsReceivedPerMinute"));
179   EXPECT_METRIC_EQ(1,
180                    metrics::NumSamples("WebRTC.Video.PliPacketsSentPerMinute"));
181   EXPECT_METRIC_EQ(
182       1, metrics::NumSamples(video_prefix + "PliPacketsReceivedPerMinute"));
183 
184   EXPECT_METRIC_EQ(
185       1, metrics::NumSamples(video_prefix + "KeyFramesSentInPermille"));
186   EXPECT_METRIC_EQ(
187       1, metrics::NumSamples("WebRTC.Video.KeyFramesReceivedInPermille"));
188 
189   EXPECT_METRIC_EQ(
190       1, metrics::NumSamples(video_prefix + "SentPacketsLostInPercent"));
191   EXPECT_METRIC_EQ(
192       1, metrics::NumSamples("WebRTC.Video.ReceivedPacketsLostInPercent"));
193 
194   EXPECT_METRIC_EQ(1, metrics::NumSamples(video_prefix + "InputWidthInPixels"));
195   EXPECT_METRIC_EQ(1,
196                    metrics::NumSamples(video_prefix + "InputHeightInPixels"));
197   EXPECT_METRIC_EQ(1, metrics::NumSamples(video_prefix + "SentWidthInPixels"));
198   EXPECT_METRIC_EQ(1, metrics::NumSamples(video_prefix + "SentHeightInPixels"));
199   EXPECT_METRIC_EQ(1,
200                    metrics::NumSamples(video_prefix + "ReceivedWidthInPixels"));
201   EXPECT_METRIC_EQ(
202       1, metrics::NumSamples(video_prefix + "ReceivedHeightInPixels"));
203 
204   EXPECT_METRIC_EQ(1, metrics::NumEvents(video_prefix + "InputWidthInPixels",
205                                          kDefaultWidth));
206   EXPECT_METRIC_EQ(1, metrics::NumEvents(video_prefix + "InputHeightInPixels",
207                                          kDefaultHeight));
208   EXPECT_METRIC_EQ(
209       1, metrics::NumEvents(video_prefix + "SentWidthInPixels", kDefaultWidth));
210   EXPECT_METRIC_EQ(1, metrics::NumEvents(video_prefix + "SentHeightInPixels",
211                                          kDefaultHeight));
212   EXPECT_METRIC_EQ(1, metrics::NumEvents(video_prefix + "ReceivedWidthInPixels",
213                                          kDefaultWidth));
214   EXPECT_METRIC_EQ(1,
215                    metrics::NumEvents(video_prefix + "ReceivedHeightInPixels",
216                                       kDefaultHeight));
217 
218   EXPECT_METRIC_EQ(1,
219                    metrics::NumSamples(video_prefix + "InputFramesPerSecond"));
220   EXPECT_METRIC_EQ(1,
221                    metrics::NumSamples(video_prefix + "SentFramesPerSecond"));
222   EXPECT_METRIC_EQ(1,
223                    metrics::NumSamples("WebRTC.Video.DecodedFramesPerSecond"));
224   EXPECT_METRIC_EQ(1,
225                    metrics::NumSamples("WebRTC.Video.RenderFramesPerSecond"));
226   EXPECT_METRIC_EQ(1,
227                    metrics::NumSamples("WebRTC.Video.DelayedFramesToRenderer"));
228 
229   EXPECT_METRIC_EQ(1,
230                    metrics::NumSamples("WebRTC.Video.JitterBufferDelayInMs"));
231   EXPECT_METRIC_EQ(1, metrics::NumSamples("WebRTC.Video.TargetDelayInMs"));
232   EXPECT_METRIC_EQ(1, metrics::NumSamples("WebRTC.Video.CurrentDelayInMs"));
233   EXPECT_METRIC_EQ(1, metrics::NumSamples("WebRTC.Video.OnewayDelayInMs"));
234 
235   EXPECT_METRIC_EQ(1, metrics::NumSamples(video_prefix + "EndToEndDelayInMs" +
236                                           video_suffix));
237   EXPECT_METRIC_EQ(1,
238                    metrics::NumSamples(video_prefix + "EndToEndDelayMaxInMs" +
239                                        video_suffix));
240   EXPECT_METRIC_EQ(1, metrics::NumSamples(video_prefix + "InterframeDelayInMs" +
241                                           video_suffix));
242   EXPECT_METRIC_EQ(1,
243                    metrics::NumSamples(video_prefix + "InterframeDelayMaxInMs" +
244                                        video_suffix));
245 
246   EXPECT_METRIC_EQ(
247       1, metrics::NumSamples("WebRTC.Video.RenderSqrtPixelsPerSecond"));
248 
249   EXPECT_METRIC_EQ(1, metrics::NumSamples(video_prefix + "EncodeTimeInMs"));
250   EXPECT_METRIC_EQ(1, metrics::NumSamples("WebRTC.Video.DecodeTimeInMs"));
251 
252   EXPECT_METRIC_EQ(1,
253                    metrics::NumSamples(video_prefix + "NumberOfPauseEvents"));
254   EXPECT_METRIC_EQ(1,
255                    metrics::NumSamples(video_prefix + "PausedTimeInPercent"));
256 
257   EXPECT_METRIC_EQ(1, metrics::NumSamples(video_prefix + "BitrateSentInKbps"));
258   EXPECT_METRIC_EQ(1,
259                    metrics::NumSamples("WebRTC.Video.BitrateReceivedInKbps"));
260   EXPECT_METRIC_EQ(
261       1, metrics::NumSamples(video_prefix + "MediaBitrateSentInKbps"));
262   EXPECT_METRIC_EQ(
263       1, metrics::NumSamples("WebRTC.Video.MediaBitrateReceivedInKbps"));
264   EXPECT_METRIC_EQ(
265       1, metrics::NumSamples(video_prefix + "PaddingBitrateSentInKbps"));
266   EXPECT_METRIC_EQ(
267       1, metrics::NumSamples("WebRTC.Video.PaddingBitrateReceivedInKbps"));
268   EXPECT_METRIC_EQ(
269       1, metrics::NumSamples(video_prefix + "RetransmittedBitrateSentInKbps"));
270   EXPECT_METRIC_EQ(1, metrics::NumSamples(
271                           "WebRTC.Video.RetransmittedBitrateReceivedInKbps"));
272 
273   EXPECT_METRIC_EQ(1, metrics::NumSamples("WebRTC.Video.SendDelayInMs"));
274   EXPECT_METRIC_EQ(1, metrics::NumSamples(video_prefix + "SendSideDelayInMs"));
275   EXPECT_METRIC_EQ(1,
276                    metrics::NumSamples(video_prefix + "SendSideDelayMaxInMs"));
277 
278   int num_rtx_samples = use_rtx ? 1 : 0;
279   EXPECT_METRIC_EQ(num_rtx_samples,
280                    metrics::NumSamples("WebRTC.Video.RtxBitrateSentInKbps"));
281   EXPECT_METRIC_EQ(
282       num_rtx_samples,
283       metrics::NumSamples("WebRTC.Video.RtxBitrateReceivedInKbps"));
284 
285   int num_red_samples = use_fec ? 1 : 0;
286   EXPECT_METRIC_EQ(num_red_samples,
287                    metrics::NumSamples("WebRTC.Video.FecBitrateSentInKbps"));
288   EXPECT_METRIC_EQ(
289       num_red_samples,
290       metrics::NumSamples("WebRTC.Video.FecBitrateReceivedInKbps"));
291   EXPECT_METRIC_EQ(
292       num_red_samples,
293       metrics::NumSamples("WebRTC.Video.ReceivedFecPacketsInPercent"));
294 }
295 
TEST_F(HistogramTest,VerifyStatsWithRtx)296 TEST_F(HistogramTest, VerifyStatsWithRtx) {
297   const bool kEnabledRtx = true;
298   const bool kEnabledRed = false;
299   const bool kScreenshare = false;
300   VerifyHistogramStats(kEnabledRtx, kEnabledRed, kScreenshare);
301 }
302 
TEST_F(HistogramTest,VerifyStatsWithRed)303 TEST_F(HistogramTest, VerifyStatsWithRed) {
304   const bool kEnabledRtx = false;
305   const bool kEnabledRed = true;
306   const bool kScreenshare = false;
307   VerifyHistogramStats(kEnabledRtx, kEnabledRed, kScreenshare);
308 }
309 
TEST_F(HistogramTest,VerifyStatsWithScreenshare)310 TEST_F(HistogramTest, VerifyStatsWithScreenshare) {
311   const bool kEnabledRtx = false;
312   const bool kEnabledRed = false;
313   const bool kScreenshare = true;
314   VerifyHistogramStats(kEnabledRtx, kEnabledRed, kScreenshare);
315 }
316 
317 }  // namespace webrtc
318