| 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 |