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
15namespace media {
16namespace cast {
17
18using testing::_;
19
20static const uint32 kSenderSsrc = 0x10203;
21static const uint32 kReceiverSsrc = 0x40506;
22static const int kInitialReceiverClockOffsetSeconds = -5;
23
24class FakeRtcpTransport : public PacedPacketSender {
25 public:
26  explicit FakeRtcpTransport(base::SimpleTestTickClock* clock)
27      : clock_(clock),
28        packet_delay_(base::TimeDelta::FromMilliseconds(42)) {}
29
30  void set_rtcp_destination(Rtcp* rtcp) { rtcp_ = rtcp; }
31
32  base::TimeDelta packet_delay() const { return packet_delay_; }
33  void set_packet_delay(base::TimeDelta delay) { packet_delay_ = delay; }
34
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
41  virtual bool SendPackets(const SendPacketVector& packets) OVERRIDE {
42    return false;
43  }
44
45  virtual bool ResendPackets(
46      const SendPacketVector& packets, const DedupInfo& dedup_info) OVERRIDE {
47    return false;
48  }
49
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
61class FakeReceiverStats : public RtpReceiverStatistics {
62 public:
63  FakeReceiverStats() {}
64  virtual ~FakeReceiverStats() {}
65
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
80class MockFrameSender {
81 public:
82  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
93class RtcpTest : public ::testing::Test {
94 protected:
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
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
139TEST_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
172TEST_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.
223TEST(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