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/rand_util.h" |
8 #include "base/test/simple_test_tick_clock.h" | 8 #include "base/test/simple_test_tick_clock.h" |
9 #include "base/time/tick_clock.h" | 9 #include "base/time/tick_clock.h" |
10 #include "media/cast/cast_environment.h" | 10 #include "media/cast/cast_environment.h" |
(...skipping 47 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
58 } | 58 } |
59 | 59 |
60 base::SimpleTestTickClock* sender_clock_; // Owned by CastEnvironment. | 60 base::SimpleTestTickClock* sender_clock_; // Owned by CastEnvironment. |
61 base::SimpleTestTickClock receiver_clock_; | 61 base::SimpleTestTickClock receiver_clock_; |
62 scoped_refptr<test::FakeSingleThreadTaskRunner> task_runner_; | 62 scoped_refptr<test::FakeSingleThreadTaskRunner> task_runner_; |
63 scoped_refptr<CastEnvironment> cast_environment_; | 63 scoped_refptr<CastEnvironment> cast_environment_; |
64 test::FakeReceiverTimeOffsetEstimator fake_offset_estimator_; | 64 test::FakeReceiverTimeOffsetEstimator fake_offset_estimator_; |
65 scoped_ptr<StatsEventSubscriber> subscriber_; | 65 scoped_ptr<StatsEventSubscriber> subscriber_; |
66 }; | 66 }; |
67 | 67 |
68 TEST_F(StatsEventSubscriberTest, Capture) { | 68 TEST_F(StatsEventSubscriberTest, CaptureEncode) { |
69 Init(VIDEO_EVENT); | 69 Init(VIDEO_EVENT); |
70 | 70 |
71 uint32 rtp_timestamp = 0; | 71 uint32 rtp_timestamp = 0; |
72 uint32 frame_id = 0; | 72 uint32 frame_id = 0; |
73 int num_frames = 10; | 73 int extra_frames = 50; |
| 74 // Only the first |extra_frames| frames logged will be taken into account |
| 75 // when computing dropped frames. |
| 76 int num_frames = StatsEventSubscriber::kMaxFrameInfoMapSize + 50; |
| 77 int dropped_frames = 0; |
74 base::TimeTicks start_time = sender_clock_->NowTicks(); | 78 base::TimeTicks start_time = sender_clock_->NowTicks(); |
| 79 // Drop half the frames during the encode step. |
75 for (int i = 0; i < num_frames; i++) { | 80 for (int i = 0; i < num_frames; i++) { |
76 cast_environment_->Logging()->InsertFrameEvent(sender_clock_->NowTicks(), | 81 cast_environment_->Logging()->InsertFrameEvent(sender_clock_->NowTicks(), |
77 FRAME_CAPTURE_BEGIN, | 82 FRAME_CAPTURE_BEGIN, |
78 VIDEO_EVENT, | 83 VIDEO_EVENT, |
79 rtp_timestamp, | 84 rtp_timestamp, |
80 frame_id); | 85 frame_id); |
81 | 86 AdvanceClocks(base::TimeDelta::FromMicroseconds(10)); |
| 87 cast_environment_->Logging()->InsertFrameEvent(sender_clock_->NowTicks(), |
| 88 FRAME_CAPTURE_END, |
| 89 VIDEO_EVENT, |
| 90 rtp_timestamp, |
| 91 frame_id); |
| 92 if (i % 2 == 0) { |
| 93 AdvanceClocks(base::TimeDelta::FromMicroseconds(10)); |
| 94 cast_environment_->Logging()->InsertEncodedFrameEvent( |
| 95 sender_clock_->NowTicks(), |
| 96 FRAME_ENCODED, |
| 97 VIDEO_EVENT, |
| 98 rtp_timestamp, |
| 99 frame_id, |
| 100 1024, |
| 101 true, |
| 102 5678); |
| 103 } else if (i < extra_frames) { |
| 104 dropped_frames++; |
| 105 } |
82 AdvanceClocks(base::TimeDelta::FromMicroseconds(34567)); | 106 AdvanceClocks(base::TimeDelta::FromMicroseconds(34567)); |
83 rtp_timestamp += 90; | 107 rtp_timestamp += 90; |
84 frame_id++; | 108 frame_id++; |
85 } | 109 } |
86 | 110 |
87 base::TimeTicks end_time = sender_clock_->NowTicks(); | 111 base::TimeTicks end_time = sender_clock_->NowTicks(); |
88 | 112 |
89 StatsEventSubscriber::StatsMap stats_map; | 113 StatsEventSubscriber::StatsMap stats_map; |
90 subscriber_->GetStatsInternal(&stats_map); | 114 subscriber_->GetStatsInternal(&stats_map); |
91 | 115 |
92 StatsEventSubscriber::StatsMap::iterator it = | 116 StatsEventSubscriber::StatsMap::iterator it = |
93 stats_map.find(StatsEventSubscriber::CAPTURE_FPS); | 117 stats_map.find(StatsEventSubscriber::CAPTURE_FPS); |
94 ASSERT_TRUE(it != stats_map.end()); | 118 ASSERT_TRUE(it != stats_map.end()); |
95 | 119 |
96 base::TimeDelta duration = end_time - start_time; | 120 base::TimeDelta duration = end_time - start_time; |
97 EXPECT_DOUBLE_EQ( | 121 EXPECT_DOUBLE_EQ( |
98 it->second, | 122 it->second, |
99 static_cast<double>(num_frames) / duration.InMillisecondsF() * 1000); | 123 static_cast<double>(num_frames) / duration.InMillisecondsF() * 1000); |
| 124 |
| 125 it = stats_map.find(StatsEventSubscriber::NUM_FRAMES_CAPTURED); |
| 126 ASSERT_TRUE(it != stats_map.end()); |
| 127 |
| 128 EXPECT_DOUBLE_EQ(it->second, static_cast<double>(num_frames)); |
| 129 |
| 130 it = stats_map.find(StatsEventSubscriber::NUM_FRAMES_DROPPED_BY_ENCODER); |
| 131 ASSERT_TRUE(it != stats_map.end()); |
| 132 |
| 133 EXPECT_DOUBLE_EQ(it->second, static_cast<double>(dropped_frames)); |
100 } | 134 } |
101 | 135 |
102 TEST_F(StatsEventSubscriberTest, Encode) { | 136 TEST_F(StatsEventSubscriberTest, Encode) { |
103 Init(VIDEO_EVENT); | 137 Init(VIDEO_EVENT); |
104 | 138 |
105 uint32 rtp_timestamp = 0; | 139 uint32 rtp_timestamp = 0; |
106 uint32 frame_id = 0; | 140 uint32 frame_id = 0; |
107 int num_frames = 10; | 141 int num_frames = 10; |
108 base::TimeTicks start_time = sender_clock_->NowTicks(); | 142 base::TimeTicks start_time = sender_clock_->NowTicks(); |
109 int total_size = 0; | 143 int total_size = 0; |
(...skipping 68 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
178 static_cast<double>(num_frames) / duration.InMillisecondsF() * 1000); | 212 static_cast<double>(num_frames) / duration.InMillisecondsF() * 1000); |
179 } | 213 } |
180 | 214 |
181 TEST_F(StatsEventSubscriberTest, PlayoutDelay) { | 215 TEST_F(StatsEventSubscriberTest, PlayoutDelay) { |
182 Init(VIDEO_EVENT); | 216 Init(VIDEO_EVENT); |
183 | 217 |
184 uint32 rtp_timestamp = 0; | 218 uint32 rtp_timestamp = 0; |
185 uint32 frame_id = 0; | 219 uint32 frame_id = 0; |
186 int num_frames = 10; | 220 int num_frames = 10; |
187 int total_delay_ms = 0; | 221 int total_delay_ms = 0; |
188 for (int i = 0; i < num_frames; i++) { | 222 int late_frames = 0; |
189 int delay_ms = base::RandInt(-50, 50); | 223 for (int i = 0, delay_ms = -50; i < num_frames; i++, delay_ms += 10) { |
190 base::TimeDelta delay = base::TimeDelta::FromMilliseconds(delay_ms); | 224 base::TimeDelta delay = base::TimeDelta::FromMilliseconds(delay_ms); |
191 total_delay_ms += delay_ms; | 225 total_delay_ms += delay_ms; |
| 226 if (delay_ms <= 0) |
| 227 late_frames++; |
192 cast_environment_->Logging()->InsertFrameEventWithDelay( | 228 cast_environment_->Logging()->InsertFrameEventWithDelay( |
193 receiver_clock_.NowTicks(), | 229 receiver_clock_.NowTicks(), |
194 FRAME_PLAYOUT, | 230 FRAME_PLAYOUT, |
195 VIDEO_EVENT, | 231 VIDEO_EVENT, |
196 rtp_timestamp, | 232 rtp_timestamp, |
197 frame_id, | 233 frame_id, |
198 delay); | 234 delay); |
199 | 235 |
200 AdvanceClocks(base::TimeDelta::FromMicroseconds(37890)); | 236 AdvanceClocks(base::TimeDelta::FromMicroseconds(37890)); |
201 rtp_timestamp += 90; | 237 rtp_timestamp += 90; |
202 frame_id++; | 238 frame_id++; |
203 } | 239 } |
204 | 240 |
205 StatsEventSubscriber::StatsMap stats_map; | 241 StatsEventSubscriber::StatsMap stats_map; |
206 subscriber_->GetStatsInternal(&stats_map); | 242 subscriber_->GetStatsInternal(&stats_map); |
207 | 243 |
208 StatsEventSubscriber::StatsMap::iterator it = | 244 StatsEventSubscriber::StatsMap::iterator it = |
209 stats_map.find(StatsEventSubscriber::AVG_PLAYOUT_DELAY_MS); | 245 stats_map.find(StatsEventSubscriber::AVG_PLAYOUT_DELAY_MS); |
210 ASSERT_TRUE(it != stats_map.end()); | 246 ASSERT_TRUE(it != stats_map.end()); |
211 | 247 |
212 EXPECT_DOUBLE_EQ( | 248 EXPECT_DOUBLE_EQ( |
213 it->second, static_cast<double>(total_delay_ms) / num_frames); | 249 it->second, static_cast<double>(total_delay_ms) / num_frames); |
| 250 |
| 251 it = stats_map.find(StatsEventSubscriber::NUM_FRAMES_LATE); |
| 252 ASSERT_TRUE(it != stats_map.end()); |
| 253 |
| 254 EXPECT_DOUBLE_EQ(it->second, late_frames); |
214 } | 255 } |
215 | 256 |
216 TEST_F(StatsEventSubscriberTest, E2ELatency) { | 257 TEST_F(StatsEventSubscriberTest, E2ELatency) { |
217 Init(VIDEO_EVENT); | 258 Init(VIDEO_EVENT); |
218 | 259 |
219 uint32 rtp_timestamp = 0; | 260 uint32 rtp_timestamp = 0; |
220 uint32 frame_id = 0; | 261 uint32 frame_id = 0; |
221 int num_frames = 10; | 262 int num_frames = 10; |
222 base::TimeDelta total_latency; | 263 base::TimeDelta total_latency; |
223 for (int i = 0; i < num_frames; i++) { | 264 for (int i = 0; i < num_frames; i++) { |
(...skipping 37 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
261 TEST_F(StatsEventSubscriberTest, Packets) { | 302 TEST_F(StatsEventSubscriberTest, Packets) { |
262 Init(VIDEO_EVENT); | 303 Init(VIDEO_EVENT); |
263 | 304 |
264 uint32 rtp_timestamp = 0; | 305 uint32 rtp_timestamp = 0; |
265 int num_packets = 10; | 306 int num_packets = 10; |
266 int num_latency_recorded_packets = 0; | 307 int num_latency_recorded_packets = 0; |
267 base::TimeTicks start_time = sender_clock_->NowTicks(); | 308 base::TimeTicks start_time = sender_clock_->NowTicks(); |
268 int total_size = 0; | 309 int total_size = 0; |
269 int retransmit_total_size = 0; | 310 int retransmit_total_size = 0; |
270 base::TimeDelta total_latency; | 311 base::TimeDelta total_latency; |
271 int num_packets_sent = 0; | 312 int num_packets_transmitted = 0; |
272 int num_packets_retransmitted = 0; | 313 int num_packets_retransmitted = 0; |
| 314 int num_packets_rtx_rejected = 0; |
273 // Every 2nd packet will be retransmitted once. | 315 // Every 2nd packet will be retransmitted once. |
274 // Every 4th packet will be retransmitted twice. | 316 // Every 4th packet will be retransmitted twice. |
275 // Every 8th packet will be retransmitted 3 times. | 317 // Every 8th packet will be retransmitted 3 times + 1 rejected retransmission. |
276 for (int i = 0; i < num_packets; i++) { | 318 for (int i = 0; i < num_packets; i++) { |
277 int size = 1000 + base::RandInt(-100, 100); | 319 int size = 1000 + base::RandInt(-100, 100); |
278 total_size += size; | 320 total_size += size; |
279 | 321 |
280 cast_environment_->Logging()->InsertPacketEvent(sender_clock_->NowTicks(), | 322 cast_environment_->Logging()->InsertPacketEvent(sender_clock_->NowTicks(), |
281 PACKET_SENT_TO_NETWORK, | 323 PACKET_SENT_TO_NETWORK, |
282 VIDEO_EVENT, | 324 VIDEO_EVENT, |
283 rtp_timestamp, | 325 rtp_timestamp, |
284 0, | 326 0, |
285 i, | 327 i, |
286 num_packets - 1, | 328 num_packets - 1, |
287 size); | 329 size); |
288 num_packets_sent++; | 330 num_packets_transmitted++; |
289 | 331 |
290 int latency_micros = 20000 + base::RandInt(-10000, 10000); | 332 int latency_micros = 20000 + base::RandInt(-10000, 10000); |
291 base::TimeDelta latency = base::TimeDelta::FromMicroseconds(latency_micros); | 333 base::TimeDelta latency = base::TimeDelta::FromMicroseconds(latency_micros); |
292 // Latency is only recorded for packets that aren't retransmitted. | 334 // Latency is only recorded for packets that aren't retransmitted. |
293 if (i % 2 != 0) { | 335 if (i % 2 != 0) { |
294 total_latency += latency; | 336 total_latency += latency; |
295 num_latency_recorded_packets++; | 337 num_latency_recorded_packets++; |
296 } | 338 } |
297 | 339 |
298 AdvanceClocks(latency); | 340 AdvanceClocks(latency); |
299 | 341 |
300 base::TimeTicks received_time = receiver_clock_.NowTicks(); | 342 base::TimeTicks received_time = receiver_clock_.NowTicks(); |
301 | 343 |
302 // Retransmission 1. | 344 // Retransmission 1. |
303 AdvanceClocks(base::TimeDelta::FromMicroseconds(12345)); | 345 AdvanceClocks(base::TimeDelta::FromMicroseconds(12345)); |
304 if (i % 2 == 0) { | 346 if (i % 2 == 0) { |
305 cast_environment_->Logging()->InsertPacketEvent( | 347 cast_environment_->Logging()->InsertPacketEvent( |
306 receiver_clock_.NowTicks(), | 348 receiver_clock_.NowTicks(), |
307 PACKET_RETRANSMITTED, | 349 PACKET_RETRANSMITTED, |
308 VIDEO_EVENT, | 350 VIDEO_EVENT, |
309 rtp_timestamp, | 351 rtp_timestamp, |
310 0, | 352 0, |
311 i, | 353 i, |
312 num_packets - 1, | 354 num_packets - 1, |
313 size); | 355 size); |
314 retransmit_total_size += size; | 356 retransmit_total_size += size; |
315 num_packets_sent++; | 357 num_packets_transmitted++; |
316 num_packets_retransmitted++; | 358 num_packets_retransmitted++; |
317 } | 359 } |
318 | 360 |
319 // Retransmission 2. | 361 // Retransmission 2. |
320 AdvanceClocks(base::TimeDelta::FromMicroseconds(13456)); | 362 AdvanceClocks(base::TimeDelta::FromMicroseconds(13456)); |
321 if (i % 4 == 0) { | 363 if (i % 4 == 0) { |
322 cast_environment_->Logging()->InsertPacketEvent( | 364 cast_environment_->Logging()->InsertPacketEvent( |
323 receiver_clock_.NowTicks(), | 365 receiver_clock_.NowTicks(), |
324 PACKET_RETRANSMITTED, | 366 PACKET_RETRANSMITTED, |
325 VIDEO_EVENT, | 367 VIDEO_EVENT, |
326 rtp_timestamp, | 368 rtp_timestamp, |
327 0, | 369 0, |
328 i, | 370 i, |
329 num_packets - 1, | 371 num_packets - 1, |
330 size); | 372 size); |
331 retransmit_total_size += size; | 373 retransmit_total_size += size; |
332 num_packets_sent++; | 374 num_packets_transmitted++; |
333 num_packets_retransmitted++; | 375 num_packets_retransmitted++; |
334 } | 376 } |
335 | 377 |
336 // Retransmission 3. | 378 // Retransmission 3. |
337 AdvanceClocks(base::TimeDelta::FromMicroseconds(14567)); | 379 AdvanceClocks(base::TimeDelta::FromMicroseconds(14567)); |
338 if (i % 8 == 0) { | 380 if (i % 8 == 0) { |
339 cast_environment_->Logging()->InsertPacketEvent( | 381 cast_environment_->Logging()->InsertPacketEvent( |
340 receiver_clock_.NowTicks(), | 382 receiver_clock_.NowTicks(), |
341 PACKET_RETRANSMITTED, | 383 PACKET_RETRANSMITTED, |
342 VIDEO_EVENT, | 384 VIDEO_EVENT, |
343 rtp_timestamp, | 385 rtp_timestamp, |
344 0, | 386 0, |
345 i, | 387 i, |
346 num_packets - 1, | 388 num_packets - 1, |
347 size); | 389 size); |
| 390 cast_environment_->Logging()->InsertPacketEvent( |
| 391 receiver_clock_.NowTicks(), |
| 392 PACKET_RTX_REJECTED, |
| 393 VIDEO_EVENT, |
| 394 rtp_timestamp, |
| 395 0, |
| 396 i, |
| 397 num_packets - 1, |
| 398 size); |
348 retransmit_total_size += size; | 399 retransmit_total_size += size; |
349 num_packets_sent++; | 400 num_packets_transmitted++; |
350 num_packets_retransmitted++; | 401 num_packets_retransmitted++; |
| 402 num_packets_rtx_rejected++; |
351 } | 403 } |
352 | 404 |
353 cast_environment_->Logging()->InsertPacketEvent(received_time, | 405 cast_environment_->Logging()->InsertPacketEvent(received_time, |
354 PACKET_RECEIVED, | 406 PACKET_RECEIVED, |
355 VIDEO_EVENT, | 407 VIDEO_EVENT, |
356 rtp_timestamp, | 408 rtp_timestamp, |
357 0, | 409 0, |
358 i, | 410 i, |
359 num_packets - 1, | 411 num_packets - 1, |
360 size); | 412 size); |
(...skipping 26 matching lines...) Expand all Loading... |
387 | 439 |
388 EXPECT_DOUBLE_EQ(it->second, | 440 EXPECT_DOUBLE_EQ(it->second, |
389 static_cast<double>(retransmit_total_size) / | 441 static_cast<double>(retransmit_total_size) / |
390 duration.InMillisecondsF() * 8); | 442 duration.InMillisecondsF() * 8); |
391 | 443 |
392 it = stats_map.find(StatsEventSubscriber::PACKET_LOSS_FRACTION); | 444 it = stats_map.find(StatsEventSubscriber::PACKET_LOSS_FRACTION); |
393 ASSERT_TRUE(it != stats_map.end()); | 445 ASSERT_TRUE(it != stats_map.end()); |
394 | 446 |
395 EXPECT_DOUBLE_EQ( | 447 EXPECT_DOUBLE_EQ( |
396 it->second, | 448 it->second, |
397 static_cast<double>(num_packets_retransmitted) / num_packets_sent); | 449 static_cast<double>(num_packets_retransmitted) / num_packets_transmitted); |
| 450 |
| 451 it = stats_map.find(StatsEventSubscriber::NUM_PACKETS_SENT); |
| 452 ASSERT_TRUE(it != stats_map.end()); |
| 453 |
| 454 EXPECT_DOUBLE_EQ(it->second, static_cast<double>(num_packets)); |
| 455 |
| 456 it = stats_map.find(StatsEventSubscriber::NUM_PACKETS_RETRANSMITTED); |
| 457 ASSERT_TRUE(it != stats_map.end()); |
| 458 |
| 459 EXPECT_DOUBLE_EQ(it->second, static_cast<double>(num_packets_retransmitted)); |
| 460 |
| 461 it = stats_map.find(StatsEventSubscriber::NUM_PACKETS_RTX_REJECTED); |
| 462 ASSERT_TRUE(it != stats_map.end()); |
| 463 |
| 464 EXPECT_DOUBLE_EQ(it->second, static_cast<double>(num_packets_rtx_rejected)); |
398 } | 465 } |
399 | 466 |
400 } // namespace cast | 467 } // namespace cast |
401 } // namespace media | 468 } // namespace media |
OLD | NEW |