OLD | NEW |
1 // Copyright 2014 The Chromium Authors. All rights reserved. | 1 // Copyright 2014 The Chromium Authors. All rights reserved. |
2 // Use of this source code is governed by a BSD-style license that can be | 2 // Use of this source code is governed by a BSD-style license that can be |
3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
4 | 4 |
5 #include "base/memory/ref_counted.h" | 5 #include "base/memory/ref_counted.h" |
6 #include "base/memory/scoped_ptr.h" | 6 #include "base/memory/scoped_ptr.h" |
| 7 #include "base/rand_util.h" |
7 #include "base/test/simple_test_tick_clock.h" | 8 #include "base/test/simple_test_tick_clock.h" |
8 #include "base/time/tick_clock.h" | 9 #include "base/time/tick_clock.h" |
9 #include "media/cast/cast_environment.h" | 10 #include "media/cast/cast_environment.h" |
10 #include "media/cast/logging/logging_defines.h" | 11 #include "media/cast/logging/logging_defines.h" |
11 #include "media/cast/logging/stats_event_subscriber.h" | 12 #include "media/cast/logging/stats_event_subscriber.h" |
| 13 #include "media/cast/test/fake_receiver_time_offset_estimator.h" |
12 #include "media/cast/test/fake_single_thread_task_runner.h" | 14 #include "media/cast/test/fake_single_thread_task_runner.h" |
13 #include "testing/gtest/include/gtest/gtest.h" | 15 #include "testing/gtest/include/gtest/gtest.h" |
14 | 16 |
| 17 namespace { |
| 18 const int kReceiverOffsetSecs = 100; |
| 19 } |
| 20 |
15 namespace media { | 21 namespace media { |
16 namespace cast { | 22 namespace cast { |
17 | 23 |
18 class StatsEventSubscriberTest : public ::testing::Test { | 24 class StatsEventSubscriberTest : public ::testing::Test { |
19 protected: | 25 protected: |
20 StatsEventSubscriberTest() | 26 StatsEventSubscriberTest() |
21 : testing_clock_(new base::SimpleTestTickClock()), | 27 : sender_clock_(new base::SimpleTestTickClock()), |
22 task_runner_(new test::FakeSingleThreadTaskRunner(testing_clock_)), | 28 task_runner_(new test::FakeSingleThreadTaskRunner(sender_clock_)), |
23 cast_environment_(new CastEnvironment( | 29 cast_environment_(new CastEnvironment( |
24 scoped_ptr<base::TickClock>(testing_clock_).Pass(), | 30 scoped_ptr<base::TickClock>(sender_clock_).Pass(), |
25 task_runner_, | 31 task_runner_, |
26 task_runner_, | 32 task_runner_, |
27 task_runner_)) {} | 33 task_runner_)), |
| 34 fake_offset_estimator_( |
| 35 base::TimeDelta::FromSeconds(kReceiverOffsetSecs)) { |
| 36 receiver_clock_.Advance(base::TimeDelta::FromSeconds(kReceiverOffsetSecs)); |
| 37 cast_environment_->Logging()->AddRawEventSubscriber( |
| 38 &fake_offset_estimator_); |
| 39 } |
28 | 40 |
29 virtual ~StatsEventSubscriberTest() { | 41 virtual ~StatsEventSubscriberTest() { |
30 if (subscriber_.get()) | 42 if (subscriber_.get()) |
31 cast_environment_->Logging()->RemoveRawEventSubscriber(subscriber_.get()); | 43 cast_environment_->Logging()->RemoveRawEventSubscriber(subscriber_.get()); |
| 44 cast_environment_->Logging()->RemoveRawEventSubscriber( |
| 45 &fake_offset_estimator_); |
| 46 } |
| 47 |
| 48 void AdvanceClocks(base::TimeDelta delta) { |
| 49 sender_clock_->Advance(delta); |
| 50 receiver_clock_.Advance(delta); |
32 } | 51 } |
33 | 52 |
34 void Init(EventMediaType event_media_type) { | 53 void Init(EventMediaType event_media_type) { |
35 DCHECK(!subscriber_.get()); | 54 DCHECK(!subscriber_.get()); |
36 subscriber_.reset(new StatsEventSubscriber(event_media_type)); | 55 subscriber_.reset(new StatsEventSubscriber( |
| 56 event_media_type, cast_environment_->Clock(), &fake_offset_estimator_)); |
37 cast_environment_->Logging()->AddRawEventSubscriber(subscriber_.get()); | 57 cast_environment_->Logging()->AddRawEventSubscriber(subscriber_.get()); |
38 } | 58 } |
39 | 59 |
40 base::SimpleTestTickClock* testing_clock_; // Owned by CastEnvironment. | 60 base::SimpleTestTickClock* sender_clock_; // Owned by CastEnvironment. |
| 61 base::SimpleTestTickClock receiver_clock_; |
41 scoped_refptr<test::FakeSingleThreadTaskRunner> task_runner_; | 62 scoped_refptr<test::FakeSingleThreadTaskRunner> task_runner_; |
42 scoped_refptr<CastEnvironment> cast_environment_; | 63 scoped_refptr<CastEnvironment> cast_environment_; |
| 64 test::FakeReceiverTimeOffsetEstimator fake_offset_estimator_; |
43 scoped_ptr<StatsEventSubscriber> subscriber_; | 65 scoped_ptr<StatsEventSubscriber> subscriber_; |
44 }; | 66 }; |
45 | 67 |
46 TEST_F(StatsEventSubscriberTest, FrameStats) { | 68 TEST_F(StatsEventSubscriberTest, EmptyStats) { |
47 Init(VIDEO_EVENT); | 69 Init(VIDEO_EVENT); |
| 70 |
| 71 StatsEventSubscriber::StatsMap stats_map; |
| 72 subscriber_->GetStatsInternal(&stats_map); |
| 73 |
| 74 EXPECT_TRUE(stats_map.empty()); |
| 75 } |
| 76 |
| 77 TEST_F(StatsEventSubscriberTest, Capture) { |
| 78 Init(VIDEO_EVENT); |
| 79 |
48 uint32 rtp_timestamp = 0; | 80 uint32 rtp_timestamp = 0; |
49 uint32 frame_id = 0; | 81 uint32 frame_id = 0; |
50 int num_frames = 10; | 82 int num_frames = 10; |
51 int frame_size = 123; | 83 base::TimeTicks start_time = sender_clock_->NowTicks(); |
52 int delay_base_ms = 10; | |
53 base::TimeTicks now; | |
54 for (int i = 0; i < num_frames; i++) { | 84 for (int i = 0; i < num_frames; i++) { |
55 now = testing_clock_->NowTicks(); | 85 cast_environment_->Logging()->InsertFrameEvent(sender_clock_->NowTicks(), |
56 cast_environment_->Logging()->InsertFrameEvent( | 86 kVideoFrameCaptured, |
57 now, kVideoFrameReceived, rtp_timestamp, frame_id); | 87 rtp_timestamp, |
58 testing_clock_->Advance(base::TimeDelta::FromMilliseconds(30)); | 88 frame_id); |
59 | 89 |
60 cast_environment_->Logging()->InsertEncodedFrameEvent( | 90 AdvanceClocks(base::TimeDelta::FromMilliseconds(30)); |
61 now, kVideoFrameEncoded, rtp_timestamp, i, frame_size, true); | 91 rtp_timestamp += 90; |
62 testing_clock_->Advance(base::TimeDelta::FromMilliseconds(30)); | 92 frame_id++; |
63 | 93 } |
| 94 |
| 95 base::TimeTicks end_time = sender_clock_->NowTicks(); |
| 96 |
| 97 StatsEventSubscriber::StatsMap stats_map; |
| 98 subscriber_->GetStatsInternal(&stats_map); |
| 99 |
| 100 StatsEventSubscriber::StatsMap::iterator it = |
| 101 stats_map.find(StatsEventSubscriber::CAPTURE_FPS); |
| 102 ASSERT_NE(it, stats_map.end()); |
| 103 |
| 104 base::TimeDelta duration = end_time - start_time; |
| 105 EXPECT_NEAR( |
| 106 it->second, |
| 107 static_cast<double>(num_frames) / duration.InMilliseconds() * 1000, |
| 108 0.05); |
| 109 } |
| 110 |
| 111 TEST_F(StatsEventSubscriberTest, Encode) { |
| 112 Init(VIDEO_EVENT); |
| 113 |
| 114 uint32 rtp_timestamp = 0; |
| 115 uint32 frame_id = 0; |
| 116 int num_frames = 10; |
| 117 base::TimeTicks start_time = sender_clock_->NowTicks(); |
| 118 int total_size = 0; |
| 119 for (int i = 0; i < num_frames; i++) { |
| 120 int size = 1000 + base::RandInt(-100, 100); |
| 121 total_size += size; |
| 122 cast_environment_->Logging()->InsertFrameEventWithSize( |
| 123 sender_clock_->NowTicks(), |
| 124 kVideoFrameEncoded, |
| 125 rtp_timestamp, |
| 126 frame_id, |
| 127 size); |
| 128 |
| 129 AdvanceClocks(base::TimeDelta::FromMilliseconds(30)); |
| 130 rtp_timestamp += 90; |
| 131 frame_id++; |
| 132 } |
| 133 |
| 134 base::TimeTicks end_time = sender_clock_->NowTicks(); |
| 135 |
| 136 StatsEventSubscriber::StatsMap stats_map; |
| 137 subscriber_->GetStatsInternal(&stats_map); |
| 138 |
| 139 StatsEventSubscriber::StatsMap::iterator it = |
| 140 stats_map.find(StatsEventSubscriber::ENCODE_FPS); |
| 141 ASSERT_NE(it, stats_map.end()); |
| 142 |
| 143 base::TimeDelta duration = end_time - start_time; |
| 144 EXPECT_NEAR( |
| 145 it->second, |
| 146 static_cast<double>(num_frames) / duration.InMilliseconds() * 1000, |
| 147 0.05); |
| 148 |
| 149 it = stats_map.find(StatsEventSubscriber::ENCODE_KBPS); |
| 150 ASSERT_NE(it, stats_map.end()); |
| 151 |
| 152 EXPECT_NEAR(it->second, |
| 153 static_cast<double>(total_size) / duration.InMilliseconds() * 8, |
| 154 0.05); |
| 155 } |
| 156 |
| 157 TEST_F(StatsEventSubscriberTest, Decode) { |
| 158 Init(VIDEO_EVENT); |
| 159 |
| 160 uint32 rtp_timestamp = 0; |
| 161 uint32 frame_id = 0; |
| 162 int num_frames = 10; |
| 163 base::TimeTicks start_time = sender_clock_->NowTicks(); |
| 164 for (int i = 0; i < num_frames; i++) { |
| 165 cast_environment_->Logging()->InsertFrameEvent(receiver_clock_.NowTicks(), |
| 166 kVideoFrameDecoded, |
| 167 rtp_timestamp, |
| 168 frame_id); |
| 169 |
| 170 AdvanceClocks(base::TimeDelta::FromMilliseconds(30)); |
| 171 rtp_timestamp += 90; |
| 172 frame_id++; |
| 173 } |
| 174 |
| 175 base::TimeTicks end_time = sender_clock_->NowTicks(); |
| 176 |
| 177 StatsEventSubscriber::StatsMap stats_map; |
| 178 subscriber_->GetStatsInternal(&stats_map); |
| 179 |
| 180 StatsEventSubscriber::StatsMap::iterator it = |
| 181 stats_map.find(StatsEventSubscriber::DECODE_FPS); |
| 182 ASSERT_NE(it, stats_map.end()); |
| 183 |
| 184 base::TimeDelta duration = end_time - start_time; |
| 185 EXPECT_NEAR( |
| 186 it->second, |
| 187 static_cast<double>(num_frames) / duration.InMilliseconds() * 1000, |
| 188 0.05); |
| 189 } |
| 190 |
| 191 TEST_F(StatsEventSubscriberTest, PlayoutDelay) { |
| 192 Init(VIDEO_EVENT); |
| 193 |
| 194 uint32 rtp_timestamp = 0; |
| 195 uint32 frame_id = 0; |
| 196 int num_frames = 10; |
| 197 int total_delay_ms = 0; |
| 198 for (int i = 0; i < num_frames; i++) { |
| 199 int delay_ms = base::RandInt(-50, 50); |
| 200 base::TimeDelta delay = base::TimeDelta::FromMilliseconds(delay_ms); |
| 201 total_delay_ms += delay_ms; |
64 cast_environment_->Logging()->InsertFrameEventWithDelay( | 202 cast_environment_->Logging()->InsertFrameEventWithDelay( |
65 now, | 203 receiver_clock_.NowTicks(), |
66 kVideoRenderDelay, | 204 kVideoRenderDelay, |
67 rtp_timestamp, | 205 rtp_timestamp, |
68 i, | 206 frame_id, |
69 base::TimeDelta::FromMilliseconds(i * delay_base_ms)); | 207 delay); |
70 testing_clock_->Advance(base::TimeDelta::FromMilliseconds(30)); | 208 |
71 | 209 AdvanceClocks(base::TimeDelta::FromMilliseconds(30)); |
72 rtp_timestamp += 90; | 210 rtp_timestamp += 90; |
73 } | 211 frame_id++; |
74 | 212 } |
75 // Verify stats. | 213 |
76 FrameStatsMap frame_stats; | 214 StatsEventSubscriber::StatsMap stats_map; |
77 subscriber_->GetFrameStats(&frame_stats); | 215 subscriber_->GetStatsInternal(&stats_map); |
78 | 216 |
79 // Size of stats equals the number of events. | 217 StatsEventSubscriber::StatsMap::iterator it = |
80 EXPECT_EQ(3u, frame_stats.size()); | 218 stats_map.find(StatsEventSubscriber::AVG_PLAYOUT_DELAY_MS); |
81 FrameStatsMap::const_iterator it = frame_stats.find(kVideoFrameReceived); | 219 ASSERT_NE(it, stats_map.end()); |
82 ASSERT_TRUE(it != frame_stats.end()); | 220 |
83 EXPECT_EQ(num_frames, it->second.event_counter); | 221 EXPECT_NEAR( |
84 | 222 it->second, static_cast<double>(total_delay_ms) / num_frames, 0.05); |
85 it = frame_stats.find(kVideoFrameEncoded); | 223 } |
86 ASSERT_TRUE(it != frame_stats.end()); | 224 |
87 | 225 TEST_F(StatsEventSubscriberTest, E2ELatency) { |
88 EXPECT_EQ(num_frames * frame_size, static_cast<int>(it->second.sum_size)); | 226 Init(VIDEO_EVENT); |
89 | 227 |
90 it = frame_stats.find(kVideoRenderDelay); | |
91 ASSERT_TRUE(it != frame_stats.end()); | |
92 | |
93 EXPECT_EQ(0, it->second.min_delay.InMilliseconds()); | |
94 EXPECT_EQ((num_frames - 1) * delay_base_ms, | |
95 it->second.max_delay.InMilliseconds()); | |
96 EXPECT_EQ((num_frames - 1) * num_frames / 2 * delay_base_ms, | |
97 it->second.sum_delay.InMilliseconds()); | |
98 } | |
99 | |
100 TEST_F(StatsEventSubscriberTest, PacketStats) { | |
101 Init(AUDIO_EVENT); | |
102 uint32 rtp_timestamp = 0; | 228 uint32 rtp_timestamp = 0; |
103 uint32 frame_id = 0; | 229 uint32 frame_id = 0; |
| 230 int num_frames = 10; |
| 231 int total_latency_ms = 0; |
| 232 for (int i = 0; i < num_frames; i++) { |
| 233 cast_environment_->Logging()->InsertFrameEvent(sender_clock_->NowTicks(), |
| 234 kVideoFrameCaptured, |
| 235 rtp_timestamp, |
| 236 frame_id); |
| 237 |
| 238 int latency_ms = 100 + base::RandInt(-50, 50); |
| 239 AdvanceClocks(base::TimeDelta::FromMilliseconds(latency_ms)); |
| 240 |
| 241 int delay_ms = base::RandInt(-50, 50); |
| 242 base::TimeDelta delay = base::TimeDelta::FromMilliseconds(delay_ms); |
| 243 total_latency_ms += latency_ms + delay_ms; |
| 244 |
| 245 cast_environment_->Logging()->InsertFrameEventWithDelay( |
| 246 receiver_clock_.NowTicks(), |
| 247 kVideoRenderDelay, |
| 248 rtp_timestamp, |
| 249 frame_id, |
| 250 delay); |
| 251 |
| 252 rtp_timestamp += 90; |
| 253 frame_id++; |
| 254 } |
| 255 |
| 256 StatsEventSubscriber::StatsMap stats_map; |
| 257 subscriber_->GetStatsInternal(&stats_map); |
| 258 |
| 259 StatsEventSubscriber::StatsMap::iterator it = |
| 260 stats_map.find(StatsEventSubscriber::AVG_E2E_LATENCY_MS); |
| 261 ASSERT_NE(it, stats_map.end()); |
| 262 |
| 263 EXPECT_NEAR( |
| 264 it->second, static_cast<double>(total_latency_ms) / num_frames, 0.05); |
| 265 } |
| 266 |
| 267 TEST_F(StatsEventSubscriberTest, Packets) { |
| 268 Init(VIDEO_EVENT); |
| 269 |
| 270 uint32 rtp_timestamp = 0; |
104 int num_packets = 10; | 271 int num_packets = 10; |
105 int packet_size = 123; | 272 int num_latency_recorded_packets = 0; |
106 base::TimeTicks first_event_time = testing_clock_->NowTicks(); | 273 base::TimeTicks start_time = sender_clock_->NowTicks(); |
107 base::TimeTicks now; | 274 int total_size = 0; |
| 275 int retransmit_total_size = 0; |
| 276 int total_latency_ms = 0; |
| 277 int num_packets_sent = 0; |
| 278 int num_packets_retransmitted = 0; |
| 279 // Every 2nd packet will be retransmitted once. |
| 280 // Every 4th packet will be retransmitted twice. |
| 281 // Every 8th packet will be retransmitted 3 times. |
108 for (int i = 0; i < num_packets; i++) { | 282 for (int i = 0; i < num_packets; i++) { |
109 now = testing_clock_->NowTicks(); | 283 int size = 1000 + base::RandInt(-100, 100); |
110 cast_environment_->Logging()->InsertPacketEvent(now, | 284 total_size += size; |
111 kAudioPacketSentToPacer, | 285 |
| 286 cast_environment_->Logging()->InsertPacketEvent(sender_clock_->NowTicks(), |
| 287 kVideoPacketSentToNetwork, |
112 rtp_timestamp, | 288 rtp_timestamp, |
113 frame_id, | |
114 0, | 289 0, |
115 10, | 290 i, |
116 packet_size); | 291 num_packets - 1, |
117 testing_clock_->Advance(base::TimeDelta::FromMilliseconds(30)); | 292 size); |
118 } | 293 num_packets_sent++; |
119 | 294 |
120 PacketStatsMap stats_map; | 295 int latency_ms = 20 + base::RandInt(-10, 10); |
121 subscriber_->GetPacketStats(&stats_map); | 296 // Latency is only recorded for packets that aren't retransmitted. |
122 | 297 if (i % 2 != 0) { |
123 // Size of stats equals the number of event types. | 298 total_latency_ms += latency_ms; |
124 EXPECT_EQ(1u, stats_map.size()); | 299 num_latency_recorded_packets++; |
125 PacketStatsMap::const_iterator it = stats_map.find(kAudioPacketSentToPacer); | 300 } |
126 ASSERT_NE(stats_map.end(), it); | 301 |
127 | 302 AdvanceClocks(base::TimeDelta::FromMilliseconds(latency_ms)); |
128 EXPECT_EQ(first_event_time, it->second.first_event_time); | 303 |
129 EXPECT_EQ(now, it->second.last_event_time); | 304 base::TimeTicks received_time = receiver_clock_.NowTicks(); |
130 EXPECT_EQ(num_packets, it->second.event_counter); | 305 |
131 EXPECT_EQ(num_packets * packet_size, static_cast<int>(it->second.sum_size)); | 306 // Retransmission 1. |
132 } | 307 AdvanceClocks(base::TimeDelta::FromMilliseconds(10)); |
133 | 308 if (i % 2 == 0) { |
134 TEST_F(StatsEventSubscriberTest, GenericStats) { | 309 cast_environment_->Logging()->InsertPacketEvent( |
135 Init(OTHER_EVENT); | 310 receiver_clock_.NowTicks(), |
136 int num_generic_events = 10; | 311 kVideoPacketRetransmitted, |
137 int value = 123; | 312 rtp_timestamp, |
138 for (int i = 0; i < num_generic_events; i++) { | 313 0, |
139 cast_environment_->Logging()->InsertGenericEvent( | 314 i, |
140 testing_clock_->NowTicks(), kRttMs, value); | 315 num_packets - 1, |
141 } | 316 size); |
142 | 317 retransmit_total_size += size; |
143 GenericStatsMap stats_map; | 318 num_packets_sent++; |
144 subscriber_->GetGenericStats(&stats_map); | 319 num_packets_retransmitted++; |
145 | 320 } |
146 EXPECT_EQ(1u, stats_map.size()); | 321 |
147 GenericStatsMap::const_iterator it = stats_map.find(kRttMs); | 322 // Retransmission 2. |
148 ASSERT_NE(stats_map.end(), it); | 323 AdvanceClocks(base::TimeDelta::FromMilliseconds(10)); |
149 | 324 if (i % 4 == 0) { |
150 EXPECT_EQ(num_generic_events, it->second.event_counter); | 325 cast_environment_->Logging()->InsertPacketEvent( |
151 EXPECT_EQ(num_generic_events * value, it->second.sum); | 326 receiver_clock_.NowTicks(), |
152 EXPECT_EQ(static_cast<uint64>(num_generic_events * value * value), | 327 kVideoPacketRetransmitted, |
153 it->second.sum_squared); | 328 rtp_timestamp, |
154 EXPECT_LE(value, it->second.min); | 329 0, |
155 EXPECT_GE(value, it->second.max); | 330 i, |
156 } | 331 num_packets - 1, |
157 | 332 size); |
158 TEST_F(StatsEventSubscriberTest, Reset) { | 333 retransmit_total_size += size; |
159 Init(VIDEO_EVENT); | 334 num_packets_sent++; |
160 cast_environment_->Logging()->InsertFrameEvent( | 335 num_packets_retransmitted++; |
161 testing_clock_->NowTicks(), kVideoFrameReceived, 0, 0); | 336 } |
162 | 337 |
163 FrameStatsMap frame_stats; | 338 // Retransmission 3. |
164 subscriber_->GetFrameStats(&frame_stats); | 339 AdvanceClocks(base::TimeDelta::FromMilliseconds(10)); |
165 EXPECT_EQ(1u, frame_stats.size()); | 340 if (i % 8 == 0) { |
166 | 341 cast_environment_->Logging()->InsertPacketEvent( |
167 subscriber_->Reset(); | 342 receiver_clock_.NowTicks(), |
168 subscriber_->GetFrameStats(&frame_stats); | 343 kVideoPacketRetransmitted, |
169 EXPECT_TRUE(frame_stats.empty()); | 344 rtp_timestamp, |
| 345 0, |
| 346 i, |
| 347 num_packets - 1, |
| 348 size); |
| 349 retransmit_total_size += size; |
| 350 num_packets_sent++; |
| 351 num_packets_retransmitted++; |
| 352 } |
| 353 |
| 354 cast_environment_->Logging()->InsertPacketEvent(received_time, |
| 355 kVideoPacketReceived, |
| 356 rtp_timestamp, |
| 357 0, |
| 358 i, |
| 359 num_packets - 1, |
| 360 size); |
| 361 } |
| 362 |
| 363 base::TimeTicks end_time = sender_clock_->NowTicks(); |
| 364 base::TimeDelta duration = end_time - start_time; |
| 365 |
| 366 StatsEventSubscriber::StatsMap stats_map; |
| 367 subscriber_->GetStatsInternal(&stats_map); |
| 368 |
| 369 // Measure AVG_NETWORK_LATENCY_MS, TRANSMISSION_KBPS, RETRANSMISSION_KBPS, |
| 370 // and PACKET_LOSS_PERCENTAGE. |
| 371 StatsEventSubscriber::StatsMap::iterator it = |
| 372 stats_map.find(StatsEventSubscriber::AVG_NETWORK_LATENCY_MS); |
| 373 ASSERT_NE(it, stats_map.end()); |
| 374 |
| 375 EXPECT_NEAR( |
| 376 it->second, |
| 377 static_cast<double>(total_latency_ms) / num_latency_recorded_packets, |
| 378 0.05); |
| 379 |
| 380 it = stats_map.find(StatsEventSubscriber::TRANSMISSION_KBPS); |
| 381 ASSERT_NE(it, stats_map.end()); |
| 382 |
| 383 EXPECT_NEAR(it->second, |
| 384 static_cast<double>(total_size) / duration.InMilliseconds() * 8, |
| 385 0.05); |
| 386 |
| 387 it = stats_map.find(StatsEventSubscriber::RETRANSMISSION_KBPS); |
| 388 ASSERT_NE(it, stats_map.end()); |
| 389 |
| 390 EXPECT_NEAR(it->second, |
| 391 static_cast<double>(retransmit_total_size) / |
| 392 duration.InMilliseconds() * 8, |
| 393 0.05); |
| 394 |
| 395 it = stats_map.find(StatsEventSubscriber::PACKET_LOSS_PERCENTAGE); |
| 396 ASSERT_NE(it, stats_map.end()); |
| 397 |
| 398 EXPECT_NEAR( |
| 399 it->second, |
| 400 static_cast<double>(num_packets_retransmitted) / num_packets_sent * 100, |
| 401 0.05); |
170 } | 402 } |
171 | 403 |
172 } // namespace cast | 404 } // namespace cast |
173 } // namespace media | 405 } // namespace media |
OLD | NEW |