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.
8 #include "base/test/simple_test_tick_clock.h"
9 #include "media/cast/cast_defines.h"
10 #include "media/cast/net/cast_transport_config.h"
11 #include "media/cast/net/pacing/paced_sender.h"
12 #include "media/cast/net/rtcp/rtcp.h"
13 #include "media/cast/test/skewed_tick_clock.h"
14 #include "testing/gmock/include/gmock/gmock.h"
21 static const uint32 kSenderSsrc
= 0x10203;
22 static const uint32 kReceiverSsrc
= 0x40506;
23 static const int kInitialReceiverClockOffsetSeconds
= -5;
25 class FakeRtcpTransport
: public PacedPacketSender
{
27 explicit FakeRtcpTransport(base::SimpleTestTickClock
* clock
)
29 packet_delay_(base::TimeDelta::FromMilliseconds(42)),
32 void set_rtcp_destination(Rtcp
* rtcp
) { rtcp_
= rtcp
; }
34 base::TimeDelta
packet_delay() const { return packet_delay_
; }
35 void set_packet_delay(base::TimeDelta delay
) { packet_delay_
= delay
; }
37 bool SendRtcpPacket(uint32 ssrc
, PacketRef packet
) override
{
38 clock_
->Advance(packet_delay_
);
40 packet_queue_
.push_back(packet
);
42 rtcp_
->IncomingRtcpPacket(&packet
->data
[0], packet
->data
.size());
47 bool SendPackets(const SendPacketVector
& packets
) override
{ return false; }
49 bool ResendPackets(const SendPacketVector
& packets
,
50 const DedupInfo
& dedup_info
) override
{
54 void CancelSendingPacket(const PacketKey
& packet_key
) override
{}
62 for (size_t i
= 0; i
< packet_queue_
.size(); ++i
) {
63 rtcp_
->IncomingRtcpPacket(&packet_queue_
[i
]->data
[0],
64 packet_queue_
[i
]->data
.size());
66 packet_queue_
.clear();
69 void ReversePacketQueue() {
70 std::reverse(packet_queue_
.begin(), packet_queue_
.end());
74 base::SimpleTestTickClock
* const clock_
;
75 base::TimeDelta packet_delay_
;
78 std::vector
<PacketRef
> packet_queue_
;
80 DISALLOW_COPY_AND_ASSIGN(FakeRtcpTransport
);
83 class MockFrameSender
{
86 virtual ~MockFrameSender() {}
88 MOCK_METHOD1(OnReceivedCastFeedback
,
89 void(const RtcpCastMessage
& cast_message
));
90 MOCK_METHOD1(OnMeasuredRoundTripTime
, void(base::TimeDelta rtt
));
93 DISALLOW_COPY_AND_ASSIGN(MockFrameSender
);
96 class RtcpTest
: public ::testing::Test
{
99 : sender_clock_(new base::SimpleTestTickClock()),
100 receiver_clock_(new test::SkewedTickClock(sender_clock_
.get())),
101 sender_to_receiver_(sender_clock_
.get()),
102 receiver_to_sender_(sender_clock_
.get()),
103 rtcp_for_sender_(base::Bind(&MockFrameSender::OnReceivedCastFeedback
,
104 base::Unretained(&mock_frame_sender_
)),
105 base::Bind(&MockFrameSender::OnMeasuredRoundTripTime
,
106 base::Unretained(&mock_frame_sender_
)),
107 RtcpLogMessageCallback(),
109 &sender_to_receiver_
,
112 rtcp_for_receiver_(RtcpCastMessageCallback(),
114 RtcpLogMessageCallback(),
115 receiver_clock_
.get(),
116 &receiver_to_sender_
,
119 sender_clock_
->Advance(base::TimeTicks::Now() - base::TimeTicks());
120 receiver_clock_
->SetSkew(
122 base::TimeDelta::FromSeconds(kInitialReceiverClockOffsetSeconds
));
124 sender_to_receiver_
.set_rtcp_destination(&rtcp_for_receiver_
);
125 receiver_to_sender_
.set_rtcp_destination(&rtcp_for_sender_
);
128 ~RtcpTest() override
{}
130 scoped_ptr
<base::SimpleTestTickClock
> sender_clock_
;
131 scoped_ptr
<test::SkewedTickClock
> receiver_clock_
;
132 FakeRtcpTransport sender_to_receiver_
;
133 FakeRtcpTransport receiver_to_sender_
;
134 MockFrameSender mock_frame_sender_
;
135 Rtcp rtcp_for_sender_
;
136 Rtcp rtcp_for_receiver_
;
138 DISALLOW_COPY_AND_ASSIGN(RtcpTest
);
141 TEST_F(RtcpTest
, LipSyncGleanedFromSenderReport
) {
142 // Initially, expect no lip-sync info receiver-side without having first
143 // received a RTCP packet.
144 base::TimeTicks reference_time
;
145 uint32 rtp_timestamp
;
146 ASSERT_FALSE(rtcp_for_receiver_
.GetLatestLipSyncTimes(&rtp_timestamp
,
149 // Send a Sender Report to the receiver.
150 const base::TimeTicks reference_time_sent
= sender_clock_
->NowTicks();
151 const uint32 rtp_timestamp_sent
= 0xbee5;
152 rtcp_for_sender_
.SendRtcpFromRtpSender(
153 reference_time_sent
, rtp_timestamp_sent
, 1, 1);
155 // Now the receiver should have lip-sync info. Confirm that the lip-sync
156 // reference time is the same as that sent.
157 EXPECT_TRUE(rtcp_for_receiver_
.GetLatestLipSyncTimes(&rtp_timestamp
,
159 const base::TimeTicks rolled_back_time
=
161 // Roll-back relative clock offset:
162 base::TimeDelta::FromSeconds(kInitialReceiverClockOffsetSeconds
) -
163 // Roll-back packet transmission time (because RTT is not yet known):
164 sender_to_receiver_
.packet_delay());
165 EXPECT_NEAR(0, (reference_time_sent
- rolled_back_time
).InMicroseconds(), 5);
166 EXPECT_EQ(rtp_timestamp_sent
, rtp_timestamp
);
169 // TODO(miu): There were a few tests here that didn't actually test anything
170 // except that the code wouldn't crash and a callback method was invoked. We
171 // need to fill-in more testing of RTCP now that much of the refactoring work
172 // has been completed.
174 TEST_F(RtcpTest
, RoundTripTimesDeterminedFromReportPingPong
) {
175 const int iterations
= 12;
176 EXPECT_CALL(mock_frame_sender_
, OnMeasuredRoundTripTime(_
))
179 // Initially, neither side knows the round trip time.
180 ASSERT_EQ(base::TimeDelta(), rtcp_for_sender_
.current_round_trip_time());
181 ASSERT_EQ(base::TimeDelta(), rtcp_for_receiver_
.current_round_trip_time());
183 // Do a number of ping-pongs, checking how the round trip times are measured
184 // by the sender and receiver.
185 base::TimeDelta expected_rtt_according_to_sender
;
186 base::TimeDelta expected_rtt_according_to_receiver
;
187 for (int i
= 0; i
< iterations
; ++i
) {
188 const base::TimeDelta one_way_trip_time
=
189 base::TimeDelta::FromMilliseconds(1 << i
);
190 sender_to_receiver_
.set_packet_delay(one_way_trip_time
);
191 receiver_to_sender_
.set_packet_delay(one_way_trip_time
);
193 // Sender --> Receiver
194 base::TimeTicks reference_time_sent
= sender_clock_
->NowTicks();
195 uint32 rtp_timestamp_sent
= 0xbee5 + i
;
196 rtcp_for_sender_
.SendRtcpFromRtpSender(
197 reference_time_sent
, rtp_timestamp_sent
, 1, 1);
198 EXPECT_EQ(expected_rtt_according_to_sender
,
199 rtcp_for_sender_
.current_round_trip_time());
200 #ifdef SENDER_PROVIDES_REPORT_BLOCK
201 EXPECT_EQ(expected_rtt_according_to_receiver
,
202 rtcp_for_receiver_
.current_round_trip_time());
205 // Receiver --> Sender
206 RtpReceiverStatistics stats
;
207 rtcp_for_receiver_
.SendRtcpFromRtpReceiver(
208 rtcp_for_receiver_
.ConvertToNTPAndSave(receiver_clock_
->NowTicks()),
209 NULL
, base::TimeDelta(), NULL
, &stats
);
210 expected_rtt_according_to_sender
= one_way_trip_time
* 2;
211 EXPECT_EQ(expected_rtt_according_to_sender
,
212 rtcp_for_sender_
.current_round_trip_time());
213 #ifdef SENDER_PROVIDES_REPORT_BLOCK
214 EXPECT_EQ(expected_rtt_according_to_receiver
,
215 rtcp_for_receiver_
.current_round_trip_time();
218 // In the next iteration of this loop, after the receiver gets the sender
219 // report, it will be measuring a round trip time consisting of two
220 // different one-way trip times.
221 expected_rtt_according_to_receiver
=
222 (one_way_trip_time
+ one_way_trip_time
* 2) / 2;
226 TEST_F(RtcpTest
, RejectOldRtcpPacket
) {
227 EXPECT_CALL(mock_frame_sender_
, OnReceivedCastFeedback(_
))
231 RtcpCastMessage
cast_message(kSenderSsrc
);
232 cast_message
.ack_frame_id
= 1;
233 receiver_to_sender_
.Pause();
234 rtcp_for_receiver_
.SendRtcpFromRtpReceiver(
235 rtcp_for_receiver_
.ConvertToNTPAndSave(
236 receiver_clock_
->NowTicks() - base::TimeDelta::FromSeconds(10)),
237 &cast_message
, base::TimeDelta(), NULL
, NULL
);
239 cast_message
.ack_frame_id
= 2;
240 rtcp_for_receiver_
.SendRtcpFromRtpReceiver(
241 rtcp_for_receiver_
.ConvertToNTPAndSave(receiver_clock_
->NowTicks()),
242 &cast_message
, base::TimeDelta(), NULL
, NULL
);
244 receiver_to_sender_
.ReversePacketQueue();
245 receiver_to_sender_
.Unpause();
248 TEST_F(RtcpTest
, NegativeTimeTicks
) {
249 EXPECT_CALL(mock_frame_sender_
, OnReceivedCastFeedback(_
))
252 // Send a RRTR with NTP timestamp that translates to a very negative
253 // value for TimeTicks.
254 RtcpCastMessage
cast_message(kSenderSsrc
);
255 cast_message
.ack_frame_id
= 2;
256 rtcp_for_receiver_
.SendRtcpFromRtpReceiver(
257 rtcp_for_receiver_
.ConvertToNTPAndSave(
258 base::TimeTicks() - base::TimeDelta::FromSeconds(5)),
259 &cast_message
, base::TimeDelta(), NULL
, NULL
);
261 cast_message
.ack_frame_id
= 1;
262 rtcp_for_receiver_
.SendRtcpFromRtpReceiver(
263 rtcp_for_receiver_
.ConvertToNTPAndSave(base::TimeTicks()),
264 &cast_message
, base::TimeDelta(), NULL
, NULL
);
267 // TODO(miu): Find a better home for this test.
268 TEST(MisplacedCastTest
, NtpAndTime
) {
269 const int64 kSecondsbetweenYear1900and2010
= INT64_C(40176 * 24 * 60 * 60);
270 const int64 kSecondsbetweenYear1900and2030
= INT64_C(47481 * 24 * 60 * 60);
272 uint32 ntp_seconds_1
= 0;
273 uint32 ntp_fraction_1
= 0;
274 base::TimeTicks input_time
= base::TimeTicks::Now();
275 ConvertTimeTicksToNtp(input_time
, &ntp_seconds_1
, &ntp_fraction_1
);
277 // Verify absolute value.
278 EXPECT_GT(ntp_seconds_1
, kSecondsbetweenYear1900and2010
);
279 EXPECT_LT(ntp_seconds_1
, kSecondsbetweenYear1900and2030
);
281 base::TimeTicks out_1
= ConvertNtpToTimeTicks(ntp_seconds_1
, ntp_fraction_1
);
282 EXPECT_EQ(input_time
, out_1
); // Verify inverse.
284 base::TimeDelta time_delta
= base::TimeDelta::FromMilliseconds(1000);
285 input_time
+= time_delta
;
287 uint32 ntp_seconds_2
= 0;
288 uint32 ntp_fraction_2
= 0;
290 ConvertTimeTicksToNtp(input_time
, &ntp_seconds_2
, &ntp_fraction_2
);
291 base::TimeTicks out_2
= ConvertNtpToTimeTicks(ntp_seconds_2
, ntp_fraction_2
);
292 EXPECT_EQ(input_time
, out_2
); // Verify inverse.
295 EXPECT_EQ((out_2
- out_1
), time_delta
);
296 EXPECT_EQ((ntp_seconds_2
- ntp_seconds_1
), UINT32_C(1));
297 EXPECT_NEAR(ntp_fraction_2
, ntp_fraction_1
, 1);
299 time_delta
= base::TimeDelta::FromMilliseconds(500);
300 input_time
+= time_delta
;
302 uint32 ntp_seconds_3
= 0;
303 uint32 ntp_fraction_3
= 0;
305 ConvertTimeTicksToNtp(input_time
, &ntp_seconds_3
, &ntp_fraction_3
);
306 base::TimeTicks out_3
= ConvertNtpToTimeTicks(ntp_seconds_3
, ntp_fraction_3
);
307 EXPECT_EQ(input_time
, out_3
); // Verify inverse.
310 EXPECT_EQ((out_3
- out_2
), time_delta
);
311 EXPECT_NEAR((ntp_fraction_3
- ntp_fraction_2
), 0xffffffff / 2, 1);