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
, Capture
) {
71 uint32 rtp_timestamp
= 0;
74 base::TimeTicks start_time
= sender_clock_
->NowTicks();
75 for (int i
= 0; i
< num_frames
; i
++) {
76 cast_environment_
->Logging()->InsertFrameEvent(sender_clock_
->NowTicks(),
82 AdvanceClocks(base::TimeDelta::FromMicroseconds(34567));
87 base::TimeTicks end_time
= sender_clock_
->NowTicks();
89 StatsEventSubscriber::StatsMap stats_map
;
90 subscriber_
->GetStatsInternal(&stats_map
);
92 StatsEventSubscriber::StatsMap::iterator it
=
93 stats_map
.find(StatsEventSubscriber::CAPTURE_FPS
);
94 ASSERT_NE(it
, stats_map
.end());
96 base::TimeDelta duration
= end_time
- start_time
;
99 static_cast<double>(num_frames
) / duration
.InMillisecondsF() * 1000);
102 TEST_F(StatsEventSubscriberTest
, Encode
) {
105 uint32 rtp_timestamp
= 0;
108 base::TimeTicks start_time
= sender_clock_
->NowTicks();
110 for (int i
= 0; i
< num_frames
; i
++) {
111 int size
= 1000 + base::RandInt(-100, 100);
113 cast_environment_
->Logging()->InsertEncodedFrameEvent(
114 sender_clock_
->NowTicks(),
115 FRAME_ENCODED
, VIDEO_EVENT
,
122 AdvanceClocks(base::TimeDelta::FromMicroseconds(35678));
127 base::TimeTicks end_time
= sender_clock_
->NowTicks();
129 StatsEventSubscriber::StatsMap stats_map
;
130 subscriber_
->GetStatsInternal(&stats_map
);
132 StatsEventSubscriber::StatsMap::iterator it
=
133 stats_map
.find(StatsEventSubscriber::ENCODE_FPS
);
134 ASSERT_NE(it
, stats_map
.end());
136 base::TimeDelta duration
= end_time
- start_time
;
139 static_cast<double>(num_frames
) / duration
.InMillisecondsF() * 1000);
141 it
= stats_map
.find(StatsEventSubscriber::ENCODE_KBPS
);
142 ASSERT_NE(it
, stats_map
.end());
144 EXPECT_DOUBLE_EQ(it
->second
,
145 static_cast<double>(total_size
) / duration
.InMillisecondsF() * 8);
148 TEST_F(StatsEventSubscriberTest
, Decode
) {
151 uint32 rtp_timestamp
= 0;
154 base::TimeTicks start_time
= sender_clock_
->NowTicks();
155 for (int i
= 0; i
< num_frames
; i
++) {
156 cast_environment_
->Logging()->InsertFrameEvent(receiver_clock_
.NowTicks(),
157 FRAME_DECODED
, VIDEO_EVENT
,
161 AdvanceClocks(base::TimeDelta::FromMicroseconds(36789));
166 base::TimeTicks end_time
= sender_clock_
->NowTicks();
168 StatsEventSubscriber::StatsMap stats_map
;
169 subscriber_
->GetStatsInternal(&stats_map
);
171 StatsEventSubscriber::StatsMap::iterator it
=
172 stats_map
.find(StatsEventSubscriber::DECODE_FPS
);
173 ASSERT_NE(it
, stats_map
.end());
175 base::TimeDelta duration
= end_time
- start_time
;
178 static_cast<double>(num_frames
) / duration
.InMillisecondsF() * 1000);
181 TEST_F(StatsEventSubscriberTest
, PlayoutDelay
) {
184 uint32 rtp_timestamp
= 0;
187 int total_delay_ms
= 0;
188 for (int i
= 0; i
< num_frames
; i
++) {
189 int delay_ms
= base::RandInt(-50, 50);
190 base::TimeDelta delay
= base::TimeDelta::FromMilliseconds(delay_ms
);
191 total_delay_ms
+= delay_ms
;
192 cast_environment_
->Logging()->InsertFrameEventWithDelay(
193 receiver_clock_
.NowTicks(),
200 AdvanceClocks(base::TimeDelta::FromMicroseconds(37890));
205 StatsEventSubscriber::StatsMap stats_map
;
206 subscriber_
->GetStatsInternal(&stats_map
);
208 StatsEventSubscriber::StatsMap::iterator it
=
209 stats_map
.find(StatsEventSubscriber::AVG_PLAYOUT_DELAY_MS
);
210 ASSERT_NE(it
, stats_map
.end());
213 it
->second
, static_cast<double>(total_delay_ms
) / num_frames
);
216 TEST_F(StatsEventSubscriberTest
, E2ELatency
) {
219 uint32 rtp_timestamp
= 0;
222 base::TimeDelta total_latency
;
223 for (int i
= 0; i
< num_frames
; i
++) {
224 cast_environment_
->Logging()->InsertFrameEvent(sender_clock_
->NowTicks(),
230 int latency_micros
= 100000 + base::RandInt(-5000, 50000);
231 base::TimeDelta latency
= base::TimeDelta::FromMicroseconds(latency_micros
);
232 AdvanceClocks(latency
);
234 int delay_micros
= base::RandInt(-50000, 50000);
235 base::TimeDelta delay
= base::TimeDelta::FromMilliseconds(delay_micros
);
236 total_latency
+= latency
+ delay
;
238 cast_environment_
->Logging()->InsertFrameEventWithDelay(
239 receiver_clock_
.NowTicks(),
250 StatsEventSubscriber::StatsMap stats_map
;
251 subscriber_
->GetStatsInternal(&stats_map
);
253 StatsEventSubscriber::StatsMap::iterator it
=
254 stats_map
.find(StatsEventSubscriber::AVG_E2E_LATENCY_MS
);
255 ASSERT_NE(it
, stats_map
.end());
258 it
->second
, total_latency
.InMillisecondsF() / num_frames
);
261 TEST_F(StatsEventSubscriberTest
, Packets
) {
264 uint32 rtp_timestamp
= 0;
265 int num_packets
= 10;
266 int num_latency_recorded_packets
= 0;
267 base::TimeTicks start_time
= sender_clock_
->NowTicks();
269 int retransmit_total_size
= 0;
270 base::TimeDelta total_latency
;
271 int num_packets_sent
= 0;
272 int num_packets_retransmitted
= 0;
273 // Every 2nd packet will be retransmitted once.
274 // Every 4th packet will be retransmitted twice.
275 // Every 8th packet will be retransmitted 3 times.
276 for (int i
= 0; i
< num_packets
; i
++) {
277 int size
= 1000 + base::RandInt(-100, 100);
280 cast_environment_
->Logging()->InsertPacketEvent(sender_clock_
->NowTicks(),
281 PACKET_SENT_TO_NETWORK
,
290 int latency_micros
= 20000 + base::RandInt(-10000, 10000);
291 base::TimeDelta latency
= base::TimeDelta::FromMicroseconds(latency_micros
);
292 // Latency is only recorded for packets that aren't retransmitted.
294 total_latency
+= latency
;
295 num_latency_recorded_packets
++;
298 AdvanceClocks(latency
);
300 base::TimeTicks received_time
= receiver_clock_
.NowTicks();
303 AdvanceClocks(base::TimeDelta::FromMicroseconds(12345));
305 cast_environment_
->Logging()->InsertPacketEvent(
306 receiver_clock_
.NowTicks(),
307 PACKET_RETRANSMITTED
,
314 retransmit_total_size
+= size
;
316 num_packets_retransmitted
++;
320 AdvanceClocks(base::TimeDelta::FromMicroseconds(13456));
322 cast_environment_
->Logging()->InsertPacketEvent(
323 receiver_clock_
.NowTicks(),
324 PACKET_RETRANSMITTED
,
331 retransmit_total_size
+= size
;
333 num_packets_retransmitted
++;
337 AdvanceClocks(base::TimeDelta::FromMicroseconds(14567));
339 cast_environment_
->Logging()->InsertPacketEvent(
340 receiver_clock_
.NowTicks(),
341 PACKET_RETRANSMITTED
,
348 retransmit_total_size
+= size
;
350 num_packets_retransmitted
++;
353 cast_environment_
->Logging()->InsertPacketEvent(received_time
,
363 base::TimeTicks end_time
= sender_clock_
->NowTicks();
364 base::TimeDelta duration
= end_time
- start_time
;
366 StatsEventSubscriber::StatsMap stats_map
;
367 subscriber_
->GetStatsInternal(&stats_map
);
369 // Measure AVG_NETWORK_LATENCY_MS, TRANSMISSION_KBPS, RETRANSMISSION_KBPS,
370 // and PACKET_LOSS_FRACTION.
371 StatsEventSubscriber::StatsMap::iterator it
=
372 stats_map
.find(StatsEventSubscriber::AVG_NETWORK_LATENCY_MS
);
373 ASSERT_NE(it
, stats_map
.end());
377 total_latency
.InMillisecondsF() / num_latency_recorded_packets
);
379 it
= stats_map
.find(StatsEventSubscriber::TRANSMISSION_KBPS
);
380 ASSERT_NE(it
, stats_map
.end());
382 EXPECT_DOUBLE_EQ(it
->second
,
383 static_cast<double>(total_size
) / duration
.InMillisecondsF() * 8);
385 it
= stats_map
.find(StatsEventSubscriber::RETRANSMISSION_KBPS
);
386 ASSERT_NE(it
, stats_map
.end());
388 EXPECT_DOUBLE_EQ(it
->second
,
389 static_cast<double>(retransmit_total_size
) /
390 duration
.InMillisecondsF() * 8);
392 it
= stats_map
.find(StatsEventSubscriber::PACKET_LOSS_FRACTION
);
393 ASSERT_NE(it
, stats_map
.end());
397 static_cast<double>(num_packets_retransmitted
) / num_packets_sent
);