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
3 // found in the LICENSE file.
5 #include "base/memory/ref_counted.h"
6 #include "base/memory/scoped_ptr.h"
7 #include "base/rand_util.h"
8 #include "base/test/simple_test_tick_clock.h"
9 #include "base/time/tick_clock.h"
10 #include "media/cast/cast_environment.h"
11 #include "media/cast/logging/logging_defines.h"
12 #include "media/cast/logging/stats_event_subscriber.h"
13 #include "media/cast/test/fake_receiver_time_offset_estimator.h"
14 #include "media/cast/test/fake_single_thread_task_runner.h"
15 #include "testing/gtest/include/gtest/gtest.h"
18 const int kReceiverOffsetSecs = 100;
24 class StatsEventSubscriberTest : public ::testing::Test {
26 StatsEventSubscriberTest()
27 : sender_clock_(new base::SimpleTestTickClock()),
28 task_runner_(new test::FakeSingleThreadTaskRunner(sender_clock_)),
29 cast_environment_(new CastEnvironment(
30 scoped_ptr<base::TickClock>(sender_clock_).Pass(),
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_);
41 virtual ~StatsEventSubscriberTest() {
42 if (subscriber_.get())
43 cast_environment_->Logging()->RemoveRawEventSubscriber(subscriber_.get());
44 cast_environment_->Logging()->RemoveRawEventSubscriber(
45 &fake_offset_estimator_);
48 void AdvanceClocks(base::TimeDelta delta) {
49 sender_clock_->Advance(delta);
50 receiver_clock_.Advance(delta);
53 void Init(EventMediaType event_media_type) {
54 DCHECK(!subscriber_.get());
55 subscriber_.reset(new StatsEventSubscriber(
56 event_media_type, cast_environment_->Clock(), &fake_offset_estimator_));
57 cast_environment_->Logging()->AddRawEventSubscriber(subscriber_.get());
60 base::SimpleTestTickClock* sender_clock_; // Owned by CastEnvironment.
61 base::SimpleTestTickClock receiver_clock_;
62 scoped_refptr<test::FakeSingleThreadTaskRunner> task_runner_;
63 scoped_refptr<CastEnvironment> cast_environment_;
64 test::FakeReceiverTimeOffsetEstimator fake_offset_estimator_;
65 scoped_ptr<StatsEventSubscriber> subscriber_;
68 TEST_F(StatsEventSubscriberTest, CaptureEncode) {
71 uint32 rtp_timestamp = 0;
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;
78 base::TimeTicks start_time = sender_clock_->NowTicks();
79 // Drop half the frames during the encode step.
80 for (int i = 0; i < num_frames; i++) {
81 cast_environment_->Logging()->InsertFrameEvent(sender_clock_->NowTicks(),
86 AdvanceClocks(base::TimeDelta::FromMicroseconds(10));
87 cast_environment_->Logging()->InsertFrameEvent(sender_clock_->NowTicks(),
93 AdvanceClocks(base::TimeDelta::FromMicroseconds(10));
94 cast_environment_->Logging()->InsertEncodedFrameEvent(
95 sender_clock_->NowTicks(),
103 } else if (i < extra_frames) {
106 AdvanceClocks(base::TimeDelta::FromMicroseconds(34567));
111 base::TimeTicks end_time = sender_clock_->NowTicks();
113 StatsEventSubscriber::StatsMap stats_map;
114 subscriber_->GetStatsInternal(&stats_map);
116 StatsEventSubscriber::StatsMap::iterator it =
117 stats_map.find(StatsEventSubscriber::CAPTURE_FPS);
118 ASSERT_TRUE(it != stats_map.end());
120 base::TimeDelta duration = end_time - start_time;
123 static_cast<double>(num_frames) / duration.InMillisecondsF() * 1000);
125 it = stats_map.find(StatsEventSubscriber::NUM_FRAMES_CAPTURED);
126 ASSERT_TRUE(it != stats_map.end());
128 EXPECT_DOUBLE_EQ(it->second, static_cast<double>(num_frames));
130 it = stats_map.find(StatsEventSubscriber::NUM_FRAMES_DROPPED_BY_ENCODER);
131 ASSERT_TRUE(it != stats_map.end());
133 EXPECT_DOUBLE_EQ(it->second, static_cast<double>(dropped_frames));
136 TEST_F(StatsEventSubscriberTest, Encode) {
139 uint32 rtp_timestamp = 0;
142 base::TimeTicks start_time = sender_clock_->NowTicks();
144 for (int i = 0; i < num_frames; i++) {
145 int size = 1000 + base::RandInt(-100, 100);
147 cast_environment_->Logging()->InsertEncodedFrameEvent(
148 sender_clock_->NowTicks(),
149 FRAME_ENCODED, VIDEO_EVENT,
156 AdvanceClocks(base::TimeDelta::FromMicroseconds(35678));
161 base::TimeTicks end_time = sender_clock_->NowTicks();
163 StatsEventSubscriber::StatsMap stats_map;
164 subscriber_->GetStatsInternal(&stats_map);
166 StatsEventSubscriber::StatsMap::iterator it =
167 stats_map.find(StatsEventSubscriber::ENCODE_FPS);
168 ASSERT_TRUE(it != stats_map.end());
170 base::TimeDelta duration = end_time - start_time;
173 static_cast<double>(num_frames) / duration.InMillisecondsF() * 1000);
175 it = stats_map.find(StatsEventSubscriber::ENCODE_KBPS);
176 ASSERT_TRUE(it != stats_map.end());
178 EXPECT_DOUBLE_EQ(it->second,
179 static_cast<double>(total_size) / duration.InMillisecondsF() * 8);
182 TEST_F(StatsEventSubscriberTest, Decode) {
185 uint32 rtp_timestamp = 0;
188 base::TimeTicks start_time = sender_clock_->NowTicks();
189 for (int i = 0; i < num_frames; i++) {
190 cast_environment_->Logging()->InsertFrameEvent(receiver_clock_.NowTicks(),
191 FRAME_DECODED, VIDEO_EVENT,
195 AdvanceClocks(base::TimeDelta::FromMicroseconds(36789));
200 base::TimeTicks end_time = sender_clock_->NowTicks();
202 StatsEventSubscriber::StatsMap stats_map;
203 subscriber_->GetStatsInternal(&stats_map);
205 StatsEventSubscriber::StatsMap::iterator it =
206 stats_map.find(StatsEventSubscriber::DECODE_FPS);
207 ASSERT_TRUE(it != stats_map.end());
209 base::TimeDelta duration = end_time - start_time;
212 static_cast<double>(num_frames) / duration.InMillisecondsF() * 1000);
215 TEST_F(StatsEventSubscriberTest, PlayoutDelay) {
218 uint32 rtp_timestamp = 0;
221 int total_delay_ms = 0;
223 for (int i = 0, delay_ms = -50; i < num_frames; i++, delay_ms += 10) {
224 base::TimeDelta delay = base::TimeDelta::FromMilliseconds(delay_ms);
225 total_delay_ms += delay_ms;
228 cast_environment_->Logging()->InsertFrameEventWithDelay(
229 receiver_clock_.NowTicks(),
236 AdvanceClocks(base::TimeDelta::FromMicroseconds(37890));
241 StatsEventSubscriber::StatsMap stats_map;
242 subscriber_->GetStatsInternal(&stats_map);
244 StatsEventSubscriber::StatsMap::iterator it =
245 stats_map.find(StatsEventSubscriber::AVG_PLAYOUT_DELAY_MS);
246 ASSERT_TRUE(it != stats_map.end());
249 it->second, static_cast<double>(total_delay_ms) / num_frames);
251 it = stats_map.find(StatsEventSubscriber::NUM_FRAMES_LATE);
252 ASSERT_TRUE(it != stats_map.end());
254 EXPECT_DOUBLE_EQ(it->second, late_frames);
257 TEST_F(StatsEventSubscriberTest, E2ELatency) {
260 uint32 rtp_timestamp = 0;
263 base::TimeDelta total_latency;
264 for (int i = 0; i < num_frames; i++) {
265 cast_environment_->Logging()->InsertFrameEvent(sender_clock_->NowTicks(),
271 int latency_micros = 100000 + base::RandInt(-5000, 50000);
272 base::TimeDelta latency = base::TimeDelta::FromMicroseconds(latency_micros);
273 AdvanceClocks(latency);
275 int delay_micros = base::RandInt(-50000, 50000);
276 base::TimeDelta delay = base::TimeDelta::FromMilliseconds(delay_micros);
277 total_latency += latency + delay;
279 cast_environment_->Logging()->InsertFrameEventWithDelay(
280 receiver_clock_.NowTicks(),
291 StatsEventSubscriber::StatsMap stats_map;
292 subscriber_->GetStatsInternal(&stats_map);
294 StatsEventSubscriber::StatsMap::iterator it =
295 stats_map.find(StatsEventSubscriber::AVG_E2E_LATENCY_MS);
296 ASSERT_TRUE(it != stats_map.end());
299 it->second, total_latency.InMillisecondsF() / num_frames);
302 TEST_F(StatsEventSubscriberTest, Packets) {
305 uint32 rtp_timestamp = 0;
306 int num_packets = 10;
307 int num_latency_recorded_packets = 0;
308 base::TimeTicks start_time = sender_clock_->NowTicks();
310 int retransmit_total_size = 0;
311 base::TimeDelta total_latency;
312 int num_packets_transmitted = 0;
313 int num_packets_retransmitted = 0;
314 int num_packets_rtx_rejected = 0;
315 // Every 2nd packet will be retransmitted once.
316 // Every 4th packet will be retransmitted twice.
317 // Every 8th packet will be retransmitted 3 times + 1 rejected retransmission.
318 for (int i = 0; i < num_packets; i++) {
319 int size = 1000 + base::RandInt(-100, 100);
322 cast_environment_->Logging()->InsertPacketEvent(sender_clock_->NowTicks(),
323 PACKET_SENT_TO_NETWORK,
330 num_packets_transmitted++;
332 int latency_micros = 20000 + base::RandInt(-10000, 10000);
333 base::TimeDelta latency = base::TimeDelta::FromMicroseconds(latency_micros);
334 // Latency is only recorded for packets that aren't retransmitted.
336 total_latency += latency;
337 num_latency_recorded_packets++;
340 AdvanceClocks(latency);
342 base::TimeTicks received_time = receiver_clock_.NowTicks();
345 AdvanceClocks(base::TimeDelta::FromMicroseconds(12345));
347 cast_environment_->Logging()->InsertPacketEvent(
348 receiver_clock_.NowTicks(),
349 PACKET_RETRANSMITTED,
356 retransmit_total_size += size;
357 num_packets_transmitted++;
358 num_packets_retransmitted++;
362 AdvanceClocks(base::TimeDelta::FromMicroseconds(13456));
364 cast_environment_->Logging()->InsertPacketEvent(
365 receiver_clock_.NowTicks(),
366 PACKET_RETRANSMITTED,
373 retransmit_total_size += size;
374 num_packets_transmitted++;
375 num_packets_retransmitted++;
379 AdvanceClocks(base::TimeDelta::FromMicroseconds(14567));
381 cast_environment_->Logging()->InsertPacketEvent(
382 receiver_clock_.NowTicks(),
383 PACKET_RETRANSMITTED,
390 cast_environment_->Logging()->InsertPacketEvent(
391 receiver_clock_.NowTicks(),
399 retransmit_total_size += size;
400 num_packets_transmitted++;
401 num_packets_retransmitted++;
402 num_packets_rtx_rejected++;
405 cast_environment_->Logging()->InsertPacketEvent(received_time,
415 base::TimeTicks end_time = sender_clock_->NowTicks();
416 base::TimeDelta duration = end_time - start_time;
418 StatsEventSubscriber::StatsMap stats_map;
419 subscriber_->GetStatsInternal(&stats_map);
421 // Measure AVG_NETWORK_LATENCY_MS, TRANSMISSION_KBPS, RETRANSMISSION_KBPS,
422 // and PACKET_LOSS_FRACTION.
423 StatsEventSubscriber::StatsMap::iterator it =
424 stats_map.find(StatsEventSubscriber::AVG_NETWORK_LATENCY_MS);
425 ASSERT_TRUE(it != stats_map.end());
429 total_latency.InMillisecondsF() / num_latency_recorded_packets);
431 it = stats_map.find(StatsEventSubscriber::TRANSMISSION_KBPS);
432 ASSERT_TRUE(it != stats_map.end());
434 EXPECT_DOUBLE_EQ(it->second,
435 static_cast<double>(total_size) / duration.InMillisecondsF() * 8);
437 it = stats_map.find(StatsEventSubscriber::RETRANSMISSION_KBPS);
438 ASSERT_TRUE(it != stats_map.end());
440 EXPECT_DOUBLE_EQ(it->second,
441 static_cast<double>(retransmit_total_size) /
442 duration.InMillisecondsF() * 8);
444 it = stats_map.find(StatsEventSubscriber::PACKET_LOSS_FRACTION);
445 ASSERT_TRUE(it != stats_map.end());
449 static_cast<double>(num_packets_retransmitted) / num_packets_transmitted);
451 it = stats_map.find(StatsEventSubscriber::NUM_PACKETS_SENT);
452 ASSERT_TRUE(it != stats_map.end());
454 EXPECT_DOUBLE_EQ(it->second, static_cast<double>(num_packets));
456 it = stats_map.find(StatsEventSubscriber::NUM_PACKETS_RETRANSMITTED);
457 ASSERT_TRUE(it != stats_map.end());
459 EXPECT_DOUBLE_EQ(it->second, static_cast<double>(num_packets_retransmitted));
461 it = stats_map.find(StatsEventSubscriber::NUM_PACKETS_RTX_REJECTED);
462 ASSERT_TRUE(it != stats_map.end());
464 EXPECT_DOUBLE_EQ(it->second, static_cast<double>(num_packets_rtx_rejected));