OLD | NEW |
| (Empty) |
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. | |
4 | |
5 #include "chrome/browser/media/webrtc_browsertest_perf.h" | |
6 | |
7 #include <stddef.h> | |
8 | |
9 #include "base/strings/stringprintf.h" | |
10 #include "base/values.h" | |
11 #include "chrome/test/base/in_process_browser_test.h" | |
12 #include "testing/perf/perf_test.h" | |
13 | |
14 static std::string Statistic(const std::string& statistic, | |
15 const std::string& bucket) { | |
16 // A ssrc stats key will be on the form stats.<bucket>-<key>.values. | |
17 // This will give a json "path" which will dig into the time series for the | |
18 // specified statistic. Buckets can be for instance ssrc_1212344, bweforvideo, | |
19 // and will each contain a bunch of statistics relevant to their nature. | |
20 // Each peer connection has a number of such buckets. | |
21 return base::StringPrintf("stats.%s-%s.values", bucket.c_str(), | |
22 statistic.c_str()); | |
23 } | |
24 | |
25 static void MaybePrintResultsForAudioReceive( | |
26 const std::string& ssrc, const base::DictionaryValue& pc_dict, | |
27 const std::string& modifier) { | |
28 std::string value; | |
29 if (!pc_dict.GetString(Statistic("audioOutputLevel", ssrc), &value)) { | |
30 // Not an audio receive stream. | |
31 return; | |
32 } | |
33 | |
34 EXPECT_TRUE(pc_dict.GetString(Statistic("bytesReceived", ssrc), &value)); | |
35 perf_test::PrintResult( | |
36 "audio_bytes", modifier, "bytes_recv", value, "bytes", false); | |
37 EXPECT_TRUE(pc_dict.GetString(Statistic("packetsLost", ssrc), &value)); | |
38 perf_test::PrintResult( | |
39 "audio_misc", modifier, "packets_lost", value, "frames", false); | |
40 EXPECT_TRUE(pc_dict.GetString(Statistic("googJitterReceived", ssrc), &value)); | |
41 perf_test::PrintResult( | |
42 "audio_rx", modifier, "goog_jitter_recv", value, "ms", false); | |
43 | |
44 EXPECT_TRUE(pc_dict.GetString(Statistic("googExpandRate", ssrc), &value)); | |
45 perf_test::PrintResult( | |
46 "audio_rates", modifier, "goog_expand_rate", value, "%", false); | |
47 EXPECT_TRUE( | |
48 pc_dict.GetString(Statistic("googSpeechExpandRate", ssrc), &value)); | |
49 perf_test::PrintResult( | |
50 "audio_rates", modifier, "goog_speech_expand_rate", value, "%", false); | |
51 EXPECT_TRUE( | |
52 pc_dict.GetString(Statistic("googSecondaryDecodedRate", ssrc), &value)); | |
53 perf_test::PrintResult( | |
54 "audio_rates", modifier, "goog_secondary_decoded_rate", value, "%", | |
55 false); | |
56 } | |
57 | |
58 static void MaybePrintResultsForAudioSend( | |
59 const std::string& ssrc, const base::DictionaryValue& pc_dict, | |
60 const std::string& modifier) { | |
61 std::string value; | |
62 if (!pc_dict.GetString(Statistic("audioInputLevel", ssrc), &value)) { | |
63 // Not an audio send stream. | |
64 return; | |
65 } | |
66 | |
67 EXPECT_TRUE(pc_dict.GetString(Statistic("bytesSent", ssrc), &value)); | |
68 perf_test::PrintResult( | |
69 "audio_bytes", modifier, "bytes_sent", value, "bytes", false); | |
70 EXPECT_TRUE(pc_dict.GetString(Statistic("googJitterReceived", ssrc), &value)); | |
71 perf_test::PrintResult( | |
72 "audio_tx", modifier, "goog_jitter_recv", value, "ms", false); | |
73 EXPECT_TRUE(pc_dict.GetString(Statistic("googRtt", ssrc), &value)); | |
74 perf_test::PrintResult( | |
75 "audio_tx", modifier, "goog_rtt", value, "ms", false); | |
76 EXPECT_TRUE( | |
77 pc_dict.GetString(Statistic("packetsSentPerSecond", ssrc), &value)); | |
78 perf_test::PrintResult("audio_tx", modifier, "packets_sent_per_second", value, | |
79 "packets", false); | |
80 } | |
81 | |
82 static void MaybePrintResultsForVideoSend( | |
83 const std::string& ssrc, const base::DictionaryValue& pc_dict, | |
84 const std::string& modifier) { | |
85 std::string value; | |
86 if (!pc_dict.GetString(Statistic("googFrameRateSent", ssrc), &value)) { | |
87 // Not a video send stream. | |
88 return; | |
89 } | |
90 | |
91 // Graph these by unit: the dashboard expects all stats in one graph to have | |
92 // the same unit (e.g. ms, fps, etc). Most graphs, like video_fps, will also | |
93 // be populated by the counterparts on the video receiving side. | |
94 perf_test::PrintResult( | |
95 "video_fps", modifier, "goog_frame_rate_sent", value, "fps", false); | |
96 EXPECT_TRUE(pc_dict.GetString(Statistic("googFrameRateInput", ssrc), &value)); | |
97 perf_test::PrintResult( | |
98 "video_fps", modifier, "goog_frame_rate_input", value, "fps", false); | |
99 | |
100 EXPECT_TRUE(pc_dict.GetString(Statistic("bytesSent", ssrc), &value)); | |
101 perf_test::PrintResult( | |
102 "video_total_bytes", modifier, "bytes_sent", value, "bytes", false); | |
103 | |
104 EXPECT_TRUE(pc_dict.GetString(Statistic("googFirsReceived", ssrc), &value)); | |
105 perf_test::PrintResult( | |
106 "video_misc", modifier, "goog_firs_recv", value, "", false); | |
107 EXPECT_TRUE(pc_dict.GetString(Statistic("googNacksReceived", ssrc), &value)); | |
108 perf_test::PrintResult( | |
109 "video_misc", modifier, "goog_nacks_recv", value, "", false); | |
110 | |
111 EXPECT_TRUE(pc_dict.GetString(Statistic("googFrameWidthSent", ssrc), &value)); | |
112 perf_test::PrintResult("video_resolution", modifier, "goog_frame_width_sent", | |
113 value, "pixels", false); | |
114 EXPECT_TRUE( | |
115 pc_dict.GetString(Statistic("googFrameHeightSent", ssrc), &value)); | |
116 perf_test::PrintResult("video_resolution", modifier, "goog_frame_height_sent", | |
117 value, "pixels", false); | |
118 | |
119 EXPECT_TRUE(pc_dict.GetString(Statistic("googAvgEncodeMs", ssrc), &value)); | |
120 perf_test::PrintResult( | |
121 "video_tx", modifier, "goog_avg_encode_ms", value, "ms", false); | |
122 EXPECT_TRUE(pc_dict.GetString(Statistic("googRtt", ssrc), &value)); | |
123 perf_test::PrintResult("video_tx", modifier, "goog_rtt", value, "ms", false); | |
124 | |
125 EXPECT_TRUE(pc_dict.GetString( | |
126 Statistic("googEncodeUsagePercent", ssrc), &value)); | |
127 perf_test::PrintResult("video_cpu_usage", modifier, | |
128 "goog_encode_usage_percent", value, "%", false); | |
129 } | |
130 | |
131 static void MaybePrintResultsForVideoReceive( | |
132 const std::string& ssrc, const base::DictionaryValue& pc_dict, | |
133 const std::string& modifier) { | |
134 std::string value; | |
135 if (!pc_dict.GetString(Statistic("googFrameRateReceived", ssrc), &value)) { | |
136 // Not a video receive stream. | |
137 return; | |
138 } | |
139 | |
140 perf_test::PrintResult( | |
141 "video_fps", modifier, "goog_frame_rate_recv", value, "fps", false); | |
142 EXPECT_TRUE( | |
143 pc_dict.GetString(Statistic("googFrameRateOutput", ssrc), &value)); | |
144 perf_test::PrintResult( | |
145 "video_fps", modifier, "goog_frame_rate_output", value, "fps", false); | |
146 | |
147 EXPECT_TRUE(pc_dict.GetString(Statistic("packetsLost", ssrc), &value)); | |
148 perf_test::PrintResult("video_misc", modifier, "packets_lost", value, | |
149 "frames", false); | |
150 | |
151 EXPECT_TRUE(pc_dict.GetString(Statistic("bytesReceived", ssrc), &value)); | |
152 perf_test::PrintResult( | |
153 "video_total_bytes", modifier, "bytes_recv", value, "bytes", false); | |
154 | |
155 EXPECT_TRUE( | |
156 pc_dict.GetString(Statistic("googFrameWidthReceived", ssrc), &value)); | |
157 perf_test::PrintResult("video_resolution", modifier, "goog_frame_width_recv", | |
158 value, "pixels", false); | |
159 EXPECT_TRUE( | |
160 pc_dict.GetString(Statistic("googFrameHeightReceived", ssrc), &value)); | |
161 perf_test::PrintResult("video_resolution", modifier, "goog_frame_height_recv", | |
162 value, "pixels", false); | |
163 | |
164 EXPECT_TRUE(pc_dict.GetString(Statistic("googCurrentDelayMs", ssrc), &value)); | |
165 perf_test::PrintResult( | |
166 "video_rx", modifier, "goog_current_delay_ms", value, "ms", false); | |
167 EXPECT_TRUE(pc_dict.GetString(Statistic("googTargetDelayMs", ssrc), &value)); | |
168 perf_test::PrintResult( | |
169 "video_rx", modifier, "goog_target_delay_ms", value, "ms", false); | |
170 EXPECT_TRUE(pc_dict.GetString(Statistic("googDecodeMs", ssrc), &value)); | |
171 perf_test::PrintResult("video_rx", modifier, "goog_decode_ms", value, "ms", | |
172 false); | |
173 EXPECT_TRUE(pc_dict.GetString(Statistic("googMaxDecodeMs", ssrc), &value)); | |
174 perf_test::PrintResult( | |
175 "video_rx", modifier, "goog_max_decode_ms", value, "ms", false); | |
176 EXPECT_TRUE(pc_dict.GetString(Statistic("googJitterBufferMs", ssrc), &value)); | |
177 perf_test::PrintResult( | |
178 "video_rx", modifier, "goog_jitter_buffer_ms", value, "ms", false); | |
179 EXPECT_TRUE(pc_dict.GetString(Statistic("googRenderDelayMs", ssrc), &value)); | |
180 perf_test::PrintResult( | |
181 "video_rx", modifier, "goog_render_delay_ms", value, "ms", false); | |
182 } | |
183 | |
184 static std::string ExtractSsrcIdentifier(const std::string& key) { | |
185 // Example key: ssrc_1234-someStatName. Grab the part before the dash. | |
186 size_t key_start_pos = 0; | |
187 size_t key_end_pos = key.find("-"); | |
188 CHECK(key_end_pos != std::string::npos) << "Could not parse key " << key; | |
189 return key.substr(key_start_pos, key_end_pos - key_start_pos); | |
190 } | |
191 | |
192 // Returns the set of unique ssrc identifiers in the call (e.g. ssrc_1234, | |
193 // ssrc_12356, etc). |stats_dict| is the .stats dict from one peer connection. | |
194 static std::set<std::string> FindAllSsrcIdentifiers( | |
195 const base::DictionaryValue& stats_dict) { | |
196 std::set<std::string> result; | |
197 base::DictionaryValue::Iterator stats_iterator(stats_dict); | |
198 | |
199 while (!stats_iterator.IsAtEnd()) { | |
200 if (stats_iterator.key().find("ssrc_") != std::string::npos) | |
201 result.insert(ExtractSsrcIdentifier(stats_iterator.key())); | |
202 stats_iterator.Advance(); | |
203 } | |
204 return result; | |
205 } | |
206 | |
207 namespace test { | |
208 | |
209 void PrintBweForVideoMetrics(const base::DictionaryValue& pc_dict, | |
210 const std::string& modifier, | |
211 const std::string& video_codec) { | |
212 std::string video_modifier = | |
213 video_codec.empty() ? modifier : modifier + "_" + video_codec; | |
214 const std::string kBweStatsKey = "bweforvideo"; | |
215 std::string value; | |
216 ASSERT_TRUE(pc_dict.GetString( | |
217 Statistic("googAvailableSendBandwidth", kBweStatsKey), &value)); | |
218 perf_test::PrintResult("bwe_stats", video_modifier, "available_send_bw", | |
219 value, "bit/s", false); | |
220 ASSERT_TRUE(pc_dict.GetString( | |
221 Statistic("googAvailableReceiveBandwidth", kBweStatsKey), &value)); | |
222 perf_test::PrintResult("bwe_stats", video_modifier, "available_recv_bw", | |
223 value, "bit/s", false); | |
224 ASSERT_TRUE(pc_dict.GetString( | |
225 Statistic("googTargetEncBitrate", kBweStatsKey), &value)); | |
226 perf_test::PrintResult("bwe_stats", video_modifier, "target_enc_bitrate", | |
227 value, "bit/s", false); | |
228 ASSERT_TRUE(pc_dict.GetString( | |
229 Statistic("googActualEncBitrate", kBweStatsKey), &value)); | |
230 perf_test::PrintResult("bwe_stats", video_modifier, "actual_enc_bitrate", | |
231 value, "bit/s", false); | |
232 ASSERT_TRUE(pc_dict.GetString( | |
233 Statistic("googTransmitBitrate", kBweStatsKey), &value)); | |
234 perf_test::PrintResult("bwe_stats", video_modifier, "transmit_bitrate", value, | |
235 "bit/s", false); | |
236 } | |
237 | |
238 void PrintMetricsForAllStreams(const base::DictionaryValue& pc_dict, | |
239 const std::string& modifier, | |
240 const std::string& video_codec) { | |
241 PrintMetricsForSendStreams(pc_dict, modifier, video_codec); | |
242 PrintMetricsForRecvStreams(pc_dict, modifier, video_codec); | |
243 } | |
244 | |
245 void PrintMetricsForSendStreams(const base::DictionaryValue& pc_dict, | |
246 const std::string& modifier, | |
247 const std::string& video_codec) { | |
248 std::string video_modifier = | |
249 video_codec.empty() ? modifier : modifier + "_" + video_codec; | |
250 const base::DictionaryValue* stats_dict; | |
251 ASSERT_TRUE(pc_dict.GetDictionary("stats", &stats_dict)); | |
252 std::set<std::string> ssrc_identifiers = FindAllSsrcIdentifiers(*stats_dict); | |
253 | |
254 std::set<std::string>::const_iterator ssrc_iterator = | |
255 ssrc_identifiers.begin(); | |
256 for (; ssrc_iterator != ssrc_identifiers.end(); ++ssrc_iterator) { | |
257 const std::string& ssrc = *ssrc_iterator; | |
258 MaybePrintResultsForAudioSend(ssrc, pc_dict, modifier); | |
259 MaybePrintResultsForVideoSend(ssrc, pc_dict, video_modifier); | |
260 } | |
261 } | |
262 | |
263 void PrintMetricsForRecvStreams(const base::DictionaryValue& pc_dict, | |
264 const std::string& modifier, | |
265 const std::string& video_codec) { | |
266 std::string video_modifier = | |
267 video_codec.empty() ? modifier : modifier + "_" + video_codec; | |
268 const base::DictionaryValue* stats_dict; | |
269 ASSERT_TRUE(pc_dict.GetDictionary("stats", &stats_dict)); | |
270 std::set<std::string> ssrc_identifiers = FindAllSsrcIdentifiers(*stats_dict); | |
271 | |
272 std::set<std::string>::const_iterator ssrc_iterator = | |
273 ssrc_identifiers.begin(); | |
274 for (; ssrc_iterator != ssrc_identifiers.end(); ++ssrc_iterator) { | |
275 const std::string& ssrc = *ssrc_iterator; | |
276 MaybePrintResultsForAudioReceive(ssrc, pc_dict, modifier); | |
277 MaybePrintResultsForVideoReceive(ssrc, pc_dict, video_modifier); | |
278 } | |
279 } | |
280 | |
281 } // namespace test | |
OLD | NEW |