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.
9 #include "base/test/simple_test_tick_clock.h"
10 #include "media/cast/cast_defines.h"
11 #include "media/cast/net/cast_transport_config.h"
12 #include "media/cast/net/pacing/paced_sender.h"
13 #include "media/cast/net/rtcp/rtcp.h"
14 #include "media/cast/test/skewed_tick_clock.h"
15 #include "testing/gmock/include/gmock/gmock.h"
22 static const uint32 kSenderSsrc
= 0x10203;
23 static const uint32 kReceiverSsrc
= 0x40506;
24 static const int kInitialReceiverClockOffsetSeconds
= -5;
26 class FakeRtcpTransport
: public PacedPacketSender
{
28 explicit FakeRtcpTransport(base::SimpleTestTickClock
* clock
)
30 packet_delay_(base::TimeDelta::FromMilliseconds(42)),
33 void set_rtcp_destination(Rtcp
* rtcp
) { rtcp_
= rtcp
; }
35 base::TimeDelta
packet_delay() const { return packet_delay_
; }
36 void set_packet_delay(base::TimeDelta delay
) { packet_delay_
= delay
; }
38 bool SendRtcpPacket(uint32 ssrc
, PacketRef packet
) final
{
39 clock_
->Advance(packet_delay_
);
41 packet_queue_
.push_back(packet
);
43 rtcp_
->IncomingRtcpPacket(&packet
->data
[0], packet
->data
.size());
48 bool SendPackets(const SendPacketVector
& packets
) final
{ return false; }
50 bool ResendPackets(const SendPacketVector
& packets
,
51 const DedupInfo
& dedup_info
) final
{
55 void CancelSendingPacket(const PacketKey
& packet_key
) final
{}
63 for (size_t i
= 0; i
< packet_queue_
.size(); ++i
) {
64 rtcp_
->IncomingRtcpPacket(&packet_queue_
[i
]->data
[0],
65 packet_queue_
[i
]->data
.size());
67 packet_queue_
.clear();
70 void ReversePacketQueue() {
71 std::reverse(packet_queue_
.begin(), packet_queue_
.end());
75 base::SimpleTestTickClock
* const clock_
;
76 base::TimeDelta packet_delay_
;
79 std::vector
<PacketRef
> packet_queue_
;
81 DISALLOW_COPY_AND_ASSIGN(FakeRtcpTransport
);
84 class MockFrameSender
{
87 virtual ~MockFrameSender() {}
89 MOCK_METHOD1(OnReceivedCastFeedback
,
90 void(const RtcpCastMessage
& cast_message
));
91 MOCK_METHOD1(OnMeasuredRoundTripTime
, void(base::TimeDelta rtt
));
94 DISALLOW_COPY_AND_ASSIGN(MockFrameSender
);
97 class RtcpTest
: public ::testing::Test
{
100 : sender_clock_(new base::SimpleTestTickClock()),
101 receiver_clock_(new test::SkewedTickClock(sender_clock_
.get())),
102 sender_to_receiver_(sender_clock_
.get()),
103 receiver_to_sender_(sender_clock_
.get()),
104 rtcp_for_sender_(base::Bind(&MockFrameSender::OnReceivedCastFeedback
,
105 base::Unretained(&mock_frame_sender_
)),
106 base::Bind(&MockFrameSender::OnMeasuredRoundTripTime
,
107 base::Unretained(&mock_frame_sender_
)),
108 RtcpLogMessageCallback(),
110 &sender_to_receiver_
,
113 rtcp_for_receiver_(RtcpCastMessageCallback(),
115 RtcpLogMessageCallback(),
116 receiver_clock_
.get(),
117 &receiver_to_sender_
,
120 sender_clock_
->Advance(base::TimeTicks::Now() - base::TimeTicks());
121 receiver_clock_
->SetSkew(
123 base::TimeDelta::FromSeconds(kInitialReceiverClockOffsetSeconds
));
125 sender_to_receiver_
.set_rtcp_destination(&rtcp_for_receiver_
);
126 receiver_to_sender_
.set_rtcp_destination(&rtcp_for_sender_
);
129 ~RtcpTest() override
{}
131 scoped_ptr
<base::SimpleTestTickClock
> sender_clock_
;
132 scoped_ptr
<test::SkewedTickClock
> receiver_clock_
;
133 FakeRtcpTransport sender_to_receiver_
;
134 FakeRtcpTransport receiver_to_sender_
;
135 MockFrameSender mock_frame_sender_
;
136 Rtcp rtcp_for_sender_
;
137 Rtcp rtcp_for_receiver_
;
139 DISALLOW_COPY_AND_ASSIGN(RtcpTest
);
142 TEST_F(RtcpTest
, LipSyncGleanedFromSenderReport
) {
143 // Initially, expect no lip-sync info receiver-side without having first
144 // received a RTCP packet.
145 base::TimeTicks reference_time
;
146 uint32 rtp_timestamp
;
147 ASSERT_FALSE(rtcp_for_receiver_
.GetLatestLipSyncTimes(&rtp_timestamp
,
150 // Send a Sender Report to the receiver.
151 const base::TimeTicks reference_time_sent
= sender_clock_
->NowTicks();
152 const uint32 rtp_timestamp_sent
= 0xbee5;
153 rtcp_for_sender_
.SendRtcpFromRtpSender(
154 reference_time_sent
, rtp_timestamp_sent
, 1, 1);
156 // Now the receiver should have lip-sync info. Confirm that the lip-sync
157 // reference time is the same as that sent.
158 EXPECT_TRUE(rtcp_for_receiver_
.GetLatestLipSyncTimes(&rtp_timestamp
,
160 const base::TimeTicks rolled_back_time
=
162 // Roll-back relative clock offset:
163 base::TimeDelta::FromSeconds(kInitialReceiverClockOffsetSeconds
) -
164 // Roll-back packet transmission time (because RTT is not yet known):
165 sender_to_receiver_
.packet_delay());
166 EXPECT_NEAR(0, (reference_time_sent
- rolled_back_time
).InMicroseconds(), 5);
167 EXPECT_EQ(rtp_timestamp_sent
, rtp_timestamp
);
170 // TODO(miu): There were a few tests here that didn't actually test anything
171 // except that the code wouldn't crash and a callback method was invoked. We
172 // need to fill-in more testing of RTCP now that much of the refactoring work
173 // has been completed.
175 TEST_F(RtcpTest
, RoundTripTimesDeterminedFromReportPingPong
) {
176 const int iterations
= 12;
177 EXPECT_CALL(mock_frame_sender_
, OnMeasuredRoundTripTime(_
))
180 // Initially, neither side knows the round trip time.
181 ASSERT_EQ(base::TimeDelta(), rtcp_for_sender_
.current_round_trip_time());
182 ASSERT_EQ(base::TimeDelta(), rtcp_for_receiver_
.current_round_trip_time());
184 // Do a number of ping-pongs, checking how the round trip times are measured
185 // by the sender and receiver.
186 base::TimeDelta expected_rtt_according_to_sender
;
187 base::TimeDelta expected_rtt_according_to_receiver
;
188 for (int i
= 0; i
< iterations
; ++i
) {
189 const base::TimeDelta one_way_trip_time
=
190 base::TimeDelta::FromMilliseconds(1 << i
);
191 sender_to_receiver_
.set_packet_delay(one_way_trip_time
);
192 receiver_to_sender_
.set_packet_delay(one_way_trip_time
);
194 // Sender --> Receiver
195 base::TimeTicks reference_time_sent
= sender_clock_
->NowTicks();
196 uint32 rtp_timestamp_sent
= 0xbee5 + i
;
197 rtcp_for_sender_
.SendRtcpFromRtpSender(
198 reference_time_sent
, rtp_timestamp_sent
, 1, 1);
199 EXPECT_EQ(expected_rtt_according_to_sender
,
200 rtcp_for_sender_
.current_round_trip_time());
201 #ifdef SENDER_PROVIDES_REPORT_BLOCK
202 EXPECT_EQ(expected_rtt_according_to_receiver
,
203 rtcp_for_receiver_
.current_round_trip_time());
206 // Receiver --> Sender
207 RtpReceiverStatistics stats
;
208 rtcp_for_receiver_
.SendRtcpFromRtpReceiver(
209 rtcp_for_receiver_
.ConvertToNTPAndSave(receiver_clock_
->NowTicks()),
210 NULL
, base::TimeDelta(), NULL
, &stats
);
211 expected_rtt_according_to_sender
= one_way_trip_time
* 2;
212 EXPECT_EQ(expected_rtt_according_to_sender
,
213 rtcp_for_sender_
.current_round_trip_time());
214 #ifdef SENDER_PROVIDES_REPORT_BLOCK
215 EXPECT_EQ(expected_rtt_according_to_receiver
,
216 rtcp_for_receiver_
.current_round_trip_time());
219 // In the next iteration of this loop, after the receiver gets the sender
220 // report, it will be measuring a round trip time consisting of two
221 // different one-way trip times.
222 expected_rtt_according_to_receiver
=
223 (one_way_trip_time
+ one_way_trip_time
* 2) / 2;
227 TEST_F(RtcpTest
, RejectOldRtcpPacket
) {
228 EXPECT_CALL(mock_frame_sender_
, OnReceivedCastFeedback(_
))
232 RtcpCastMessage
cast_message(kSenderSsrc
);
233 cast_message
.ack_frame_id
= 1;
234 receiver_to_sender_
.Pause();
235 rtcp_for_receiver_
.SendRtcpFromRtpReceiver(
236 rtcp_for_receiver_
.ConvertToNTPAndSave(
237 receiver_clock_
->NowTicks() - base::TimeDelta::FromSeconds(10)),
238 &cast_message
, base::TimeDelta(), NULL
, NULL
);
240 cast_message
.ack_frame_id
= 2;
241 rtcp_for_receiver_
.SendRtcpFromRtpReceiver(
242 rtcp_for_receiver_
.ConvertToNTPAndSave(receiver_clock_
->NowTicks()),
243 &cast_message
, base::TimeDelta(), NULL
, NULL
);
245 receiver_to_sender_
.ReversePacketQueue();
246 receiver_to_sender_
.Unpause();
249 TEST_F(RtcpTest
, NegativeTimeTicks
) {
250 EXPECT_CALL(mock_frame_sender_
, OnReceivedCastFeedback(_
))
253 // Send a RRTR with NTP timestamp that translates to a very negative
254 // value for TimeTicks.
255 RtcpCastMessage
cast_message(kSenderSsrc
);
256 cast_message
.ack_frame_id
= 2;
257 rtcp_for_receiver_
.SendRtcpFromRtpReceiver(
258 rtcp_for_receiver_
.ConvertToNTPAndSave(
259 base::TimeTicks() - base::TimeDelta::FromSeconds(5)),
260 &cast_message
, base::TimeDelta(), NULL
, NULL
);
262 cast_message
.ack_frame_id
= 1;
263 rtcp_for_receiver_
.SendRtcpFromRtpReceiver(
264 rtcp_for_receiver_
.ConvertToNTPAndSave(base::TimeTicks()),
265 &cast_message
, base::TimeDelta(), NULL
, NULL
);
268 // TODO(miu): Find a better home for this test.
269 TEST(MisplacedCastTest
, NtpAndTime
) {
270 const int64 kSecondsbetweenYear1900and2010
= INT64_C(40176 * 24 * 60 * 60);
271 const int64 kSecondsbetweenYear1900and2030
= INT64_C(47481 * 24 * 60 * 60);
273 uint32 ntp_seconds_1
= 0;
274 uint32 ntp_fraction_1
= 0;
275 base::TimeTicks input_time
= base::TimeTicks::Now();
276 ConvertTimeTicksToNtp(input_time
, &ntp_seconds_1
, &ntp_fraction_1
);
278 // Verify absolute value.
279 EXPECT_GT(ntp_seconds_1
, kSecondsbetweenYear1900and2010
);
280 EXPECT_LT(ntp_seconds_1
, kSecondsbetweenYear1900and2030
);
282 base::TimeTicks out_1
= ConvertNtpToTimeTicks(ntp_seconds_1
, ntp_fraction_1
);
283 EXPECT_EQ(input_time
, out_1
); // Verify inverse.
285 base::TimeDelta time_delta
= base::TimeDelta::FromMilliseconds(1000);
286 input_time
+= time_delta
;
288 uint32 ntp_seconds_2
= 0;
289 uint32 ntp_fraction_2
= 0;
291 ConvertTimeTicksToNtp(input_time
, &ntp_seconds_2
, &ntp_fraction_2
);
292 base::TimeTicks out_2
= ConvertNtpToTimeTicks(ntp_seconds_2
, ntp_fraction_2
);
293 EXPECT_EQ(input_time
, out_2
); // Verify inverse.
296 EXPECT_EQ((out_2
- out_1
), time_delta
);
297 EXPECT_EQ((ntp_seconds_2
- ntp_seconds_1
), UINT32_C(1));
298 EXPECT_NEAR(ntp_fraction_2
, ntp_fraction_1
, 1);
300 time_delta
= base::TimeDelta::FromMilliseconds(500);
301 input_time
+= time_delta
;
303 uint32 ntp_seconds_3
= 0;
304 uint32 ntp_fraction_3
= 0;
306 ConvertTimeTicksToNtp(input_time
, &ntp_seconds_3
, &ntp_fraction_3
);
307 base::TimeTicks out_3
= ConvertNtpToTimeTicks(ntp_seconds_3
, ntp_fraction_3
);
308 EXPECT_EQ(input_time
, out_3
); // Verify inverse.
311 EXPECT_EQ((out_3
- out_2
), time_delta
);
312 EXPECT_NEAR((ntp_fraction_3
- ntp_fraction_2
), 0xffffffff / 2, 1);