1 // Copyright 2013 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
5 #include "chrome/browser/media/webrtc_browsertest_perf.h"
7 #include "base/strings/stringprintf.h"
8 #include "base/values.h"
9 #include "chrome/test/base/in_process_browser_test.h"
10 #include "testing/perf/perf_test.h"
12 static std::string
Statistic(const std::string
& statistic
,
13 const std::string
& bucket
) {
14 // A ssrc stats key will be on the form stats.<bucket>-<key>.values.
15 // This will give a json "path" which will dig into the time series for the
16 // specified statistic. Buckets can be for instance ssrc_1212344, bweforvideo,
17 // and will each contain a bunch of statistics relevant to their nature.
18 // Each peer connection has a number of such buckets.
19 return base::StringPrintf("stats.%s-%s.values", bucket
.c_str(),
23 static bool MaybePrintResultsForAudioReceive(
24 const std::string
& ssrc
, const base::DictionaryValue
& pc_dict
) {
26 if (!pc_dict
.GetString(Statistic("audioOutputLevel", ssrc
), &value
)) {
27 // Not an audio receive stream.
31 EXPECT_TRUE(pc_dict
.GetString(Statistic("bytesReceived", ssrc
), &value
));
32 perf_test::PrintResult("audio_recv", "", "bytes_recv", value
, "bytes", false);
33 EXPECT_TRUE(pc_dict
.GetString(Statistic("packetsLost", ssrc
), &value
));
34 perf_test::PrintResult("audio_recv", "", "packets_lost", value
, "", false);
39 static bool MaybePrintResultsForAudioSend(
40 const std::string
& ssrc
, const base::DictionaryValue
& pc_dict
) {
42 if (!pc_dict
.GetString(Statistic("audioInputLevel", ssrc
), &value
)) {
43 // Not an audio send stream.
47 EXPECT_TRUE(pc_dict
.GetString(Statistic("bytesSent", ssrc
), &value
));
48 perf_test::PrintResult("audio_recv", "", "bytes_sent", value
, "bytes", false);
49 EXPECT_TRUE(pc_dict
.GetString(Statistic("googJitterReceived", ssrc
), &value
));
50 perf_test::PrintResult("audio_recv", "", "goog_jitter_recv", value
, "",
52 EXPECT_TRUE(pc_dict
.GetString(Statistic("googRtt", ssrc
), &value
));
53 perf_test::PrintResult("audio_recv", "", "goog_rtt", value
, "ms", false);
57 static bool MaybePrintResultsForVideoReceive(
58 const std::string
& ssrc
, const base::DictionaryValue
& pc_dict
) {
60 if (!pc_dict
.GetString(Statistic("googFrameRateInput", ssrc
), &value
)) {
61 // Not a video receive stream.
65 perf_test::PrintResult("video_recv", "", "goog_frame_rate_input", value
,
68 EXPECT_TRUE(pc_dict
.GetString(Statistic("googFrameRateSent", ssrc
), &value
));
69 perf_test::PrintResult("video_recv", "", "goog_frame_rate_sent", value
, "fps",
71 EXPECT_TRUE(pc_dict
.GetString(Statistic("bytesSent", ssrc
), &value
));
72 perf_test::PrintResult("video_recv", "", "bytes_sent", value
, "bytes", false);
73 EXPECT_TRUE(pc_dict
.GetString(Statistic("googFirsReceived", ssrc
), &value
));
74 perf_test::PrintResult("video_recv", "", "goog_firs_recv", value
, "", false);
75 EXPECT_TRUE(pc_dict
.GetString(Statistic("googNacksReceived", ssrc
), &value
));
76 perf_test::PrintResult("video_recv", "", "goog_nacks_recv", value
, "", false);
77 EXPECT_TRUE(pc_dict
.GetString(Statistic("googFrameWidthSent", ssrc
), &value
));
78 perf_test::PrintResult("video_recv", "", "goog_frame_width_sent", value
,
81 pc_dict
.GetString(Statistic("googFrameHeightSent", ssrc
), &value
));
82 perf_test::PrintResult("video_recv", "", "goog_frame_height_sent", value
,
87 static bool MaybePrintResultsForVideoSend(
88 const std::string
& ssrc
, const base::DictionaryValue
& pc_dict
) {
90 if (!pc_dict
.GetString(Statistic("googFrameRateOutput", ssrc
), &value
)) {
91 // Not a video receive stream.
95 perf_test::PrintResult("video_send", "", "goog_frame_rate_output", value
,
98 EXPECT_TRUE(pc_dict
.GetString(Statistic("packetsLost", ssrc
), &value
));
99 perf_test::PrintResult("video_send", "", "packets_lost", value
, "packets",
102 pc_dict
.GetString(Statistic("googFrameWidthReceived", ssrc
), &value
));
103 perf_test::PrintResult("video_send", "", "goog_frame_width_recv", value
,
106 pc_dict
.GetString(Statistic("googFrameHeightReceived", ssrc
), &value
));
107 perf_test::PrintResult("video_send", "", "goog_frame_height_recv", value
,
110 pc_dict
.GetString(Statistic("googFrameRateReceived", ssrc
), &value
));
111 perf_test::PrintResult("video_send", "", "goog_frame_rate_recv", value
, "fps",
113 EXPECT_TRUE(pc_dict
.GetString(Statistic("googCurrentDelayMs", ssrc
), &value
));
114 perf_test::PrintResult("video_send", "", "goog_current_delay_ms", value
, "ms",
116 EXPECT_TRUE(pc_dict
.GetString(Statistic("googTargetDelayMs", ssrc
), &value
));
117 perf_test::PrintResult("video_send", "", "goog_target_delay_ms", value
, "ms",
119 EXPECT_TRUE(pc_dict
.GetString(Statistic("googDecodeMs", ssrc
), &value
));
120 perf_test::PrintResult("video_send", "", "goog_decode_ms", value
, "ms",
122 EXPECT_TRUE(pc_dict
.GetString(Statistic("googMaxDecodeMs", ssrc
), &value
));
123 perf_test::PrintResult("video_send", "", "goog_max_decode_ms", value
, "ms",
125 EXPECT_TRUE(pc_dict
.GetString(Statistic("googJitterBufferMs", ssrc
), &value
));
126 perf_test::PrintResult("video_send", "", "goog_jitter_buffer_ms", value
, "ms",
128 EXPECT_TRUE(pc_dict
.GetString(Statistic("googRenderDelayMs", ssrc
), &value
));
129 perf_test::PrintResult("video_send", "", "goog_render_delay_ms", value
, "ms",
135 static std::string
ExtractSsrcIdentifier(const std::string
& key
) {
136 // Example key: ssrc_1234-someStatName. Grab the part before the dash.
137 size_t key_start_pos
= 0;
138 size_t key_end_pos
= key
.find("-");
139 CHECK(key_end_pos
!= std::string::npos
) << "Could not parse key " << key
;
140 return key
.substr(key_start_pos
, key_end_pos
- key_start_pos
);
143 // Returns the set of unique ssrc identifiers in the call (e.g. ssrc_1234,
144 // ssrc_12356, etc). |stats_dict| is the .stats dict from one peer connection.
145 static std::set
<std::string
> FindAllSsrcIdentifiers(
146 const base::DictionaryValue
& stats_dict
) {
147 std::set
<std::string
> result
;
148 base::DictionaryValue::Iterator
stats_iterator(stats_dict
);
150 while (!stats_iterator
.IsAtEnd()) {
151 if (stats_iterator
.key().find("ssrc_") != std::string::npos
)
152 result
.insert(ExtractSsrcIdentifier(stats_iterator
.key()));
153 stats_iterator
.Advance();
158 void PrintBweForVideoMetrics(const base::DictionaryValue
& pc_dict
) {
159 const std::string kBweStatsKey
= "bweforvideo";
161 ASSERT_TRUE(pc_dict
.GetString(
162 Statistic("googAvailableSendBandwidth", kBweStatsKey
), &value
));
163 perf_test::PrintResult("bwe_stats", "", "available_send_bw", value
, "bytes/s",
165 ASSERT_TRUE(pc_dict
.GetString(
166 Statistic("googAvailableReceiveBandwidth", kBweStatsKey
), &value
));
167 perf_test::PrintResult("bwe_stats", "", "available_recv_bw", value
, "bytes/s",
169 ASSERT_TRUE(pc_dict
.GetString(Statistic("googTargetEncBitrate", kBweStatsKey
),
171 perf_test::PrintResult("bwe_stats", "", "target_enc_bitrate", value
, "bit/s",
173 ASSERT_TRUE(pc_dict
.GetString(Statistic("googActualEncBitrate", kBweStatsKey
),
175 perf_test::PrintResult("bwe_stats", "", "actual_enc_bitrate", value
, "bit/s",
177 ASSERT_TRUE(pc_dict
.GetString(Statistic("googTransmitBitrate", kBweStatsKey
),
179 perf_test::PrintResult("bwe_stats", "", "transmit_bitrate", value
, "bit/s",
183 void PrintMetricsForAllStreams(const base::DictionaryValue
& pc_dict
) {
184 const base::DictionaryValue
* stats_dict
;
185 ASSERT_TRUE(pc_dict
.GetDictionary("stats", &stats_dict
));
186 std::set
<std::string
> ssrc_identifiers
= FindAllSsrcIdentifiers(*stats_dict
);
188 std::set
<std::string
>::const_iterator ssrc_iterator
=
189 ssrc_identifiers
.begin();
190 for (; ssrc_iterator
!= ssrc_identifiers
.end(); ++ssrc_iterator
) {
191 // Figure out which stream type this ssrc represents and print all the
192 // interesting metrics for it.
193 const std::string
& ssrc
= *ssrc_iterator
;
194 bool did_recognize_stream_type
=
195 MaybePrintResultsForAudioReceive(ssrc
, pc_dict
) ||
196 MaybePrintResultsForAudioSend(ssrc
, pc_dict
) ||
197 MaybePrintResultsForVideoReceive(ssrc
, pc_dict
) ||
198 MaybePrintResultsForVideoSend(ssrc
, pc_dict
);
199 ASSERT_TRUE(did_recognize_stream_type
) << "Failed to figure out which "
200 "kind of stream SSRC " << ssrc