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.
4
5 #include <stdint.h>
6
7 #include "base/test/simple_test_tick_clock.h"
8 #include "media/cast/cast_defines.h"
9 #include "media/cast/net/cast_transport_config.h"
10 #include "media/cast/net/pacing/paced_sender.h"
11 #include "media/cast/net/rtcp/rtcp.h"
12 #include "media/cast/test/skewed_tick_clock.h"
13 #include "testing/gmock/include/gmock/gmock.h"
14
15 namespace media {
16 namespace cast {
17
18 using testing::_;
19
20 static const uint32 kSenderSsrc = 0x10203;
21 static const uint32 kReceiverSsrc = 0x40506;
22 static const int kInitialReceiverClockOffsetSeconds = -5;
23
24 class FakeRtcpTransport : public PacedPacketSender {
25 public:
FakeRtcpTransport(base::SimpleTestTickClock * clock)26 explicit FakeRtcpTransport(base::SimpleTestTickClock* clock)
27 : clock_(clock),
28 packet_delay_(base::TimeDelta::FromMilliseconds(42)) {}
29
set_rtcp_destination(Rtcp * rtcp)30 void set_rtcp_destination(Rtcp* rtcp) { rtcp_ = rtcp; }
31
packet_delay() const32 base::TimeDelta packet_delay() const { return packet_delay_; }
set_packet_delay(base::TimeDelta delay)33 void set_packet_delay(base::TimeDelta delay) { packet_delay_ = delay; }
34
SendRtcpPacket(uint32 ssrc,PacketRef packet)35 virtual bool SendRtcpPacket(uint32 ssrc, PacketRef packet) OVERRIDE {
36 clock_->Advance(packet_delay_);
37 rtcp_->IncomingRtcpPacket(&packet->data[0], packet->data.size());
38 return true;
39 }
40
SendPackets(const SendPacketVector & packets)41 virtual bool SendPackets(const SendPacketVector& packets) OVERRIDE {
42 return false;
43 }
44
ResendPackets(const SendPacketVector & packets,const DedupInfo & dedup_info)45 virtual bool ResendPackets(
46 const SendPacketVector& packets, const DedupInfo& dedup_info) OVERRIDE {
47 return false;
48 }
49
CancelSendingPacket(const PacketKey & packet_key)50 virtual void CancelSendingPacket(const PacketKey& packet_key) OVERRIDE {
51 }
52
53 private:
54 base::SimpleTestTickClock* const clock_;
55 base::TimeDelta packet_delay_;
56 Rtcp* rtcp_;
57
58 DISALLOW_COPY_AND_ASSIGN(FakeRtcpTransport);
59 };
60
61 class FakeReceiverStats : public RtpReceiverStatistics {
62 public:
FakeReceiverStats()63 FakeReceiverStats() {}
~FakeReceiverStats()64 virtual ~FakeReceiverStats() {}
65
GetStatistics(uint8 * fraction_lost,uint32 * cumulative_lost,uint32 * extended_high_sequence_number,uint32 * jitter)66 virtual void GetStatistics(uint8* fraction_lost,
67 uint32* cumulative_lost,
68 uint32* extended_high_sequence_number,
69 uint32* jitter) OVERRIDE {
70 *fraction_lost = 0;
71 *cumulative_lost = 0;
72 *extended_high_sequence_number = 0;
73 *jitter = 0;
74 }
75
76 private:
77 DISALLOW_COPY_AND_ASSIGN(FakeReceiverStats);
78 };
79
80 class MockFrameSender {
81 public:
MockFrameSender()82 MockFrameSender() {}
~MockFrameSender()83 virtual ~MockFrameSender() {}
84
85 MOCK_METHOD1(OnReceivedCastFeedback,
86 void(const RtcpCastMessage& cast_message));
87 MOCK_METHOD1(OnMeasuredRoundTripTime, void(base::TimeDelta rtt));
88
89 private:
90 DISALLOW_COPY_AND_ASSIGN(MockFrameSender);
91 };
92
93 class RtcpTest : public ::testing::Test {
94 protected:
RtcpTest()95 RtcpTest()
96 : sender_clock_(new base::SimpleTestTickClock()),
97 receiver_clock_(new test::SkewedTickClock(sender_clock_.get())),
98 sender_to_receiver_(sender_clock_.get()),
99 receiver_to_sender_(sender_clock_.get()),
100 rtcp_for_sender_(base::Bind(&MockFrameSender::OnReceivedCastFeedback,
101 base::Unretained(&mock_frame_sender_)),
102 base::Bind(&MockFrameSender::OnMeasuredRoundTripTime,
103 base::Unretained(&mock_frame_sender_)),
104 RtcpLogMessageCallback(),
105 sender_clock_.get(),
106 &sender_to_receiver_,
107 kSenderSsrc,
108 kReceiverSsrc),
109 rtcp_for_receiver_(RtcpCastMessageCallback(),
110 RtcpRttCallback(),
111 RtcpLogMessageCallback(),
112 receiver_clock_.get(),
113 &receiver_to_sender_,
114 kReceiverSsrc,
115 kSenderSsrc) {
116 sender_clock_->Advance(base::TimeTicks::Now() - base::TimeTicks());
117 receiver_clock_->SetSkew(
118 1.0, // No skew.
119 base::TimeDelta::FromSeconds(kInitialReceiverClockOffsetSeconds));
120
121 sender_to_receiver_.set_rtcp_destination(&rtcp_for_receiver_);
122 receiver_to_sender_.set_rtcp_destination(&rtcp_for_sender_);
123 }
124
~RtcpTest()125 virtual ~RtcpTest() {}
126
127 scoped_ptr<base::SimpleTestTickClock> sender_clock_;
128 scoped_ptr<test::SkewedTickClock> receiver_clock_;
129 FakeRtcpTransport sender_to_receiver_;
130 FakeRtcpTransport receiver_to_sender_;
131 MockFrameSender mock_frame_sender_;
132 Rtcp rtcp_for_sender_;
133 Rtcp rtcp_for_receiver_;
134 FakeReceiverStats stats_;
135
136 DISALLOW_COPY_AND_ASSIGN(RtcpTest);
137 };
138
TEST_F(RtcpTest,LipSyncGleanedFromSenderReport)139 TEST_F(RtcpTest, LipSyncGleanedFromSenderReport) {
140 // Initially, expect no lip-sync info receiver-side without having first
141 // received a RTCP packet.
142 base::TimeTicks reference_time;
143 uint32 rtp_timestamp;
144 ASSERT_FALSE(rtcp_for_receiver_.GetLatestLipSyncTimes(&rtp_timestamp,
145 &reference_time));
146
147 // Send a Sender Report to the receiver.
148 const base::TimeTicks reference_time_sent = sender_clock_->NowTicks();
149 const uint32 rtp_timestamp_sent = 0xbee5;
150 rtcp_for_sender_.SendRtcpFromRtpSender(
151 reference_time_sent, rtp_timestamp_sent, 1, 1);
152
153 // Now the receiver should have lip-sync info. Confirm that the lip-sync
154 // reference time is the same as that sent.
155 EXPECT_TRUE(rtcp_for_receiver_.GetLatestLipSyncTimes(&rtp_timestamp,
156 &reference_time));
157 const base::TimeTicks rolled_back_time =
158 (reference_time -
159 // Roll-back relative clock offset:
160 base::TimeDelta::FromSeconds(kInitialReceiverClockOffsetSeconds) -
161 // Roll-back packet transmission time (because RTT is not yet known):
162 sender_to_receiver_.packet_delay());
163 EXPECT_NEAR(0, (reference_time_sent - rolled_back_time).InMicroseconds(), 5);
164 EXPECT_EQ(rtp_timestamp_sent, rtp_timestamp);
165 }
166
167 // TODO(miu): There were a few tests here that didn't actually test anything
168 // except that the code wouldn't crash and a callback method was invoked. We
169 // need to fill-in more testing of RTCP now that much of the refactoring work
170 // has been completed.
171
TEST_F(RtcpTest,RoundTripTimesDeterminedFromReportPingPong)172 TEST_F(RtcpTest, RoundTripTimesDeterminedFromReportPingPong) {
173 const int iterations = 12;
174 EXPECT_CALL(mock_frame_sender_, OnMeasuredRoundTripTime(_))
175 .Times(iterations);
176
177 // Initially, neither side knows the round trip time.
178 ASSERT_EQ(base::TimeDelta(), rtcp_for_sender_.current_round_trip_time());
179 ASSERT_EQ(base::TimeDelta(), rtcp_for_receiver_.current_round_trip_time());
180
181 // Do a number of ping-pongs, checking how the round trip times are measured
182 // by the sender and receiver.
183 base::TimeDelta expected_rtt_according_to_sender;
184 base::TimeDelta expected_rtt_according_to_receiver;
185 for (int i = 0; i < iterations; ++i) {
186 const base::TimeDelta one_way_trip_time =
187 base::TimeDelta::FromMilliseconds(1 << i);
188 sender_to_receiver_.set_packet_delay(one_way_trip_time);
189 receiver_to_sender_.set_packet_delay(one_way_trip_time);
190
191 // Sender --> Receiver
192 base::TimeTicks reference_time_sent = sender_clock_->NowTicks();
193 uint32 rtp_timestamp_sent = 0xbee5 + i;
194 rtcp_for_sender_.SendRtcpFromRtpSender(
195 reference_time_sent, rtp_timestamp_sent, 1, 1);
196 EXPECT_EQ(expected_rtt_according_to_sender,
197 rtcp_for_sender_.current_round_trip_time());
198 #ifdef SENDER_PROVIDES_REPORT_BLOCK
199 EXPECT_EQ(expected_rtt_according_to_receiver,
200 rtcp_for_receiver_.current_round_trip_time());
201 #endif
202
203 // Receiver --> Sender
204 rtcp_for_receiver_.SendRtcpFromRtpReceiver(
205 NULL, base::TimeDelta(), NULL, &stats_);
206 expected_rtt_according_to_sender = one_way_trip_time * 2;
207 EXPECT_EQ(expected_rtt_according_to_sender,
208 rtcp_for_sender_.current_round_trip_time());
209 #ifdef SENDER_PROVIDES_REPORT_BLOCK
210 EXPECT_EQ(expected_rtt_according_to_receiver,
211 rtcp_for_receiver_.current_round_trip_time();
212 #endif
213
214 // In the next iteration of this loop, after the receiver gets the sender
215 // report, it will be measuring a round trip time consisting of two
216 // different one-way trip times.
217 expected_rtt_according_to_receiver =
218 (one_way_trip_time + one_way_trip_time * 2) / 2;
219 }
220 }
221
222 // TODO(miu): Find a better home for this test.
223 TEST(MisplacedCastTest, NtpAndTime) {
224 const int64 kSecondsbetweenYear1900and2010 = INT64_C(40176 * 24 * 60 * 60);
225 const int64 kSecondsbetweenYear1900and2030 = INT64_C(47481 * 24 * 60 * 60);
226
227 uint32 ntp_seconds_1 = 0;
228 uint32 ntp_fraction_1 = 0;
229 base::TimeTicks input_time = base::TimeTicks::Now();
230 ConvertTimeTicksToNtp(input_time, &ntp_seconds_1, &ntp_fraction_1);
231
232 // Verify absolute value.
233 EXPECT_GT(ntp_seconds_1, kSecondsbetweenYear1900and2010);
234 EXPECT_LT(ntp_seconds_1, kSecondsbetweenYear1900and2030);
235
236 base::TimeTicks out_1 = ConvertNtpToTimeTicks(ntp_seconds_1, ntp_fraction_1);
237 EXPECT_EQ(input_time, out_1); // Verify inverse.
238
239 base::TimeDelta time_delta = base::TimeDelta::FromMilliseconds(1000);
240 input_time += time_delta;
241
242 uint32 ntp_seconds_2 = 0;
243 uint32 ntp_fraction_2 = 0;
244
245 ConvertTimeTicksToNtp(input_time, &ntp_seconds_2, &ntp_fraction_2);
246 base::TimeTicks out_2 = ConvertNtpToTimeTicks(ntp_seconds_2, ntp_fraction_2);
247 EXPECT_EQ(input_time, out_2); // Verify inverse.
248
249 // Verify delta.
250 EXPECT_EQ((out_2 - out_1), time_delta);
251 EXPECT_EQ((ntp_seconds_2 - ntp_seconds_1), UINT32_C(1));
252 EXPECT_NEAR(ntp_fraction_2, ntp_fraction_1, 1);
253
254 time_delta = base::TimeDelta::FromMilliseconds(500);
255 input_time += time_delta;
256
257 uint32 ntp_seconds_3 = 0;
258 uint32 ntp_fraction_3 = 0;
259
260 ConvertTimeTicksToNtp(input_time, &ntp_seconds_3, &ntp_fraction_3);
261 base::TimeTicks out_3 = ConvertNtpToTimeTicks(ntp_seconds_3, ntp_fraction_3);
262 EXPECT_EQ(input_time, out_3); // Verify inverse.
263
264 // Verify delta.
265 EXPECT_EQ((out_3 - out_2), time_delta);
266 EXPECT_NEAR((ntp_fraction_3 - ntp_fraction_2), 0xffffffff / 2, 1);
267 }
268
269 } // namespace cast
270 } // namespace media
271