11320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci// Copyright 2014 The Chromium Authors. All rights reserved.
21320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci// Use of this source code is governed by a BSD-style license that can be
31320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci// found in the LICENSE file.
41320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci
51320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci#include "base/memory/ref_counted.h"
61320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci#include "base/memory/scoped_ptr.h"
71320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci#include "base/test/simple_test_tick_clock.h"
81320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci#include "base/time/tick_clock.h"
91320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci#include "media/cast/cast_environment.h"
101320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci#include "media/cast/logging/logging_defines.h"
111320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci#include "media/cast/logging/receiver_time_offset_estimator_impl.h"
121320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci#include "media/cast/test/fake_single_thread_task_runner.h"
131320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci#include "testing/gtest/include/gtest/gtest.h"
141320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci
151320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tuccinamespace media {
161320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tuccinamespace cast {
171320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci
181320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucciclass ReceiverTimeOffsetEstimatorImplTest : public ::testing::Test {
191320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci protected:
201320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  ReceiverTimeOffsetEstimatorImplTest()
211320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci      : sender_clock_(new base::SimpleTestTickClock()),
221320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci        task_runner_(new test::FakeSingleThreadTaskRunner(sender_clock_)),
231320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci        cast_environment_(new CastEnvironment(
241320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci            scoped_ptr<base::TickClock>(sender_clock_).Pass(),
251320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci            task_runner_,
261320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci            task_runner_,
271320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci            task_runner_)) {
281320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci    cast_environment_->Logging()->AddRawEventSubscriber(&estimator_);
291320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  }
301320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci
311320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  virtual ~ReceiverTimeOffsetEstimatorImplTest() {
321320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci    cast_environment_->Logging()->RemoveRawEventSubscriber(&estimator_);
331320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  }
341320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci
351320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  void AdvanceClocks(base::TimeDelta time) {
361320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci    sender_clock_->Advance(time);
371320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci    receiver_clock_.Advance(time);
381320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  }
391320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci
401320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  base::SimpleTestTickClock* sender_clock_;  // Owned by CastEnvironment.
411320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  scoped_refptr<test::FakeSingleThreadTaskRunner> task_runner_;
421320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  scoped_refptr<CastEnvironment> cast_environment_;
431320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  base::SimpleTestTickClock receiver_clock_;
441320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  ReceiverTimeOffsetEstimatorImpl estimator_;
451320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci};
461320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci
47// Suppose the true offset is 100ms.
48// Event A occurred at sender time 20ms.
49// Event B occurred at receiver time 130ms. (sender time 30ms)
50// Event C occurred at sender time 60ms.
51// Then the bound after all 3 events have arrived is [130-60=70, 130-20=110].
52TEST_F(ReceiverTimeOffsetEstimatorImplTest, EstimateOffset) {
53  int64 true_offset_ms = 100;
54  receiver_clock_.Advance(base::TimeDelta::FromMilliseconds(true_offset_ms));
55
56  base::TimeDelta lower_bound;
57  base::TimeDelta upper_bound;
58
59  EXPECT_FALSE(estimator_.GetReceiverOffsetBounds(&lower_bound, &upper_bound));
60
61  RtpTimestamp rtp_timestamp = 0;
62  uint32 frame_id = 0;
63
64  AdvanceClocks(base::TimeDelta::FromMilliseconds(20));
65
66  cast_environment_->Logging()->InsertEncodedFrameEvent(
67      sender_clock_->NowTicks(),
68      FRAME_ENCODED, VIDEO_EVENT,
69      rtp_timestamp,
70      frame_id,
71      1234,
72      true,
73      5678);
74
75  cast_environment_->Logging()->InsertPacketEvent(
76      sender_clock_->NowTicks(),
77      PACKET_SENT_TO_NETWORK, VIDEO_EVENT,
78      rtp_timestamp,
79      frame_id,
80      56, 78, 1500);
81
82  EXPECT_FALSE(estimator_.GetReceiverOffsetBounds(&lower_bound, &upper_bound));
83
84  AdvanceClocks(base::TimeDelta::FromMilliseconds(10));
85  cast_environment_->Logging()->InsertFrameEvent(
86      receiver_clock_.NowTicks(), FRAME_ACK_SENT, VIDEO_EVENT,
87      rtp_timestamp, frame_id);
88
89  cast_environment_->Logging()->InsertPacketEvent(
90      receiver_clock_.NowTicks(),
91      PACKET_RECEIVED, VIDEO_EVENT,
92      rtp_timestamp,
93      frame_id,
94      56, 78, 1500);
95
96  EXPECT_FALSE(estimator_.GetReceiverOffsetBounds(&lower_bound, &upper_bound));
97
98  AdvanceClocks(base::TimeDelta::FromMilliseconds(30));
99  cast_environment_->Logging()->InsertFrameEvent(
100      sender_clock_->NowTicks(), FRAME_ACK_RECEIVED, VIDEO_EVENT,
101      rtp_timestamp, frame_id);
102
103  EXPECT_TRUE(estimator_.GetReceiverOffsetBounds(&lower_bound, &upper_bound));
104
105  int64 lower_bound_ms = lower_bound.InMilliseconds();
106  int64 upper_bound_ms = upper_bound.InMilliseconds();
107  EXPECT_EQ(70, lower_bound_ms);
108  EXPECT_EQ(110, upper_bound_ms);
109  EXPECT_GE(true_offset_ms, lower_bound_ms);
110  EXPECT_LE(true_offset_ms, upper_bound_ms);
111}
112
113// Same scenario as above, but event C arrives before event B. It doens't mean
114// event C occurred before event B.
115TEST_F(ReceiverTimeOffsetEstimatorImplTest, EventCArrivesBeforeEventB) {
116  int64 true_offset_ms = 100;
117  receiver_clock_.Advance(base::TimeDelta::FromMilliseconds(true_offset_ms));
118
119  base::TimeDelta lower_bound;
120  base::TimeDelta upper_bound;
121
122  EXPECT_FALSE(estimator_.GetReceiverOffsetBounds(&lower_bound, &upper_bound));
123
124  RtpTimestamp rtp_timestamp = 0;
125  uint32 frame_id = 0;
126
127  AdvanceClocks(base::TimeDelta::FromMilliseconds(20));
128
129  cast_environment_->Logging()->InsertEncodedFrameEvent(
130      sender_clock_->NowTicks(),
131      FRAME_ENCODED, VIDEO_EVENT,
132      rtp_timestamp,
133      frame_id,
134      1234,
135      true,
136      5678);
137
138  cast_environment_->Logging()->InsertPacketEvent(
139      sender_clock_->NowTicks(),
140      PACKET_SENT_TO_NETWORK, VIDEO_EVENT,
141      rtp_timestamp,
142      frame_id,
143      56, 78, 1500);
144
145  EXPECT_FALSE(estimator_.GetReceiverOffsetBounds(&lower_bound, &upper_bound));
146
147  AdvanceClocks(base::TimeDelta::FromMilliseconds(10));
148  base::TimeTicks event_b_time = receiver_clock_.NowTicks();
149  AdvanceClocks(base::TimeDelta::FromMilliseconds(30));
150  base::TimeTicks event_c_time = sender_clock_->NowTicks();
151
152  cast_environment_->Logging()->InsertFrameEvent(
153      event_c_time, FRAME_ACK_RECEIVED, VIDEO_EVENT, rtp_timestamp, frame_id);
154
155  EXPECT_FALSE(estimator_.GetReceiverOffsetBounds(&lower_bound, &upper_bound));
156
157  cast_environment_->Logging()->InsertPacketEvent(
158      event_b_time,
159      PACKET_RECEIVED, VIDEO_EVENT,
160      rtp_timestamp,
161      frame_id,
162      56, 78, 1500);
163
164  cast_environment_->Logging()->InsertFrameEvent(
165      event_b_time, FRAME_ACK_SENT, VIDEO_EVENT, rtp_timestamp, frame_id);
166
167  EXPECT_TRUE(estimator_.GetReceiverOffsetBounds(&lower_bound, &upper_bound));
168
169  int64 lower_bound_ms = lower_bound.InMilliseconds();
170  int64 upper_bound_ms = upper_bound.InMilliseconds();
171  EXPECT_EQ(70, lower_bound_ms);
172  EXPECT_EQ(110, upper_bound_ms);
173  EXPECT_GE(true_offset_ms, lower_bound_ms);
174  EXPECT_LE(true_offset_ms, upper_bound_ms);
175}
176
177TEST_F(ReceiverTimeOffsetEstimatorImplTest, MultipleIterations) {
178  int64 true_offset_ms = 100;
179  receiver_clock_.Advance(base::TimeDelta::FromMilliseconds(true_offset_ms));
180
181  base::TimeDelta lower_bound;
182  base::TimeDelta upper_bound;
183
184  RtpTimestamp rtp_timestamp_a = 0;
185  int frame_id_a = 0;
186  RtpTimestamp rtp_timestamp_b = 90;
187  int frame_id_b = 1;
188  RtpTimestamp rtp_timestamp_c = 180;
189  int frame_id_c = 2;
190
191  // Frame 1 times: [20, 30+100, 60]
192  // Frame 2 times: [30, 50+100, 55]
193  // Frame 3 times: [77, 80+100, 110]
194  // Bound should end up at [95, 103]
195  // Events times in chronological order: 20, 30 x2, 50, 55, 60, 77, 80, 110
196  AdvanceClocks(base::TimeDelta::FromMilliseconds(20));
197  cast_environment_->Logging()->InsertEncodedFrameEvent(
198      sender_clock_->NowTicks(),
199      FRAME_ENCODED, VIDEO_EVENT,
200      rtp_timestamp_a,
201      frame_id_a,
202      1234,
203      true,
204      5678);
205
206  cast_environment_->Logging()->InsertPacketEvent(
207      sender_clock_->NowTicks(),
208      PACKET_SENT_TO_NETWORK, VIDEO_EVENT,
209      rtp_timestamp_a,
210      frame_id_a,
211      56, 78, 1500);
212
213  AdvanceClocks(base::TimeDelta::FromMilliseconds(10));
214  cast_environment_->Logging()->InsertEncodedFrameEvent(
215      sender_clock_->NowTicks(),
216      FRAME_ENCODED, VIDEO_EVENT,
217      rtp_timestamp_b,
218      frame_id_b,
219      1234,
220      true,
221      5678);
222
223  cast_environment_->Logging()->InsertPacketEvent(
224      sender_clock_->NowTicks(),
225      PACKET_SENT_TO_NETWORK, VIDEO_EVENT,
226      rtp_timestamp_b,
227      frame_id_b,
228      56, 78, 1500);
229
230  cast_environment_->Logging()->InsertFrameEvent(
231      receiver_clock_.NowTicks(), FRAME_ACK_SENT, VIDEO_EVENT,
232      rtp_timestamp_a, frame_id_a);
233
234  AdvanceClocks(base::TimeDelta::FromMilliseconds(20));
235
236  cast_environment_->Logging()->InsertPacketEvent(
237      receiver_clock_.NowTicks(),
238      PACKET_RECEIVED, VIDEO_EVENT,
239      rtp_timestamp_b,
240      frame_id_b,
241      56, 78, 1500);
242
243  cast_environment_->Logging()->InsertFrameEvent(
244      receiver_clock_.NowTicks(), FRAME_ACK_SENT, VIDEO_EVENT,
245      rtp_timestamp_b, frame_id_b);
246
247  AdvanceClocks(base::TimeDelta::FromMilliseconds(5));
248  cast_environment_->Logging()->InsertFrameEvent(sender_clock_->NowTicks(),
249                                                 FRAME_ACK_RECEIVED,
250                                                 VIDEO_EVENT,
251                                                 rtp_timestamp_b,
252                                                 frame_id_b);
253
254  AdvanceClocks(base::TimeDelta::FromMilliseconds(5));
255  cast_environment_->Logging()->InsertFrameEvent(sender_clock_->NowTicks(),
256                                                 FRAME_ACK_RECEIVED,
257                                                 VIDEO_EVENT,
258                                                 rtp_timestamp_a,
259                                                 frame_id_a);
260
261  AdvanceClocks(base::TimeDelta::FromMilliseconds(17));
262  cast_environment_->Logging()->InsertEncodedFrameEvent(
263      sender_clock_->NowTicks(),
264      FRAME_ENCODED, VIDEO_EVENT,
265      rtp_timestamp_c,
266      frame_id_c,
267      1234,
268      true,
269      5678);
270
271  cast_environment_->Logging()->InsertPacketEvent(
272      sender_clock_->NowTicks(),
273      PACKET_SENT_TO_NETWORK, VIDEO_EVENT,
274      rtp_timestamp_c,
275      frame_id_c,
276      56, 78, 1500);
277
278  AdvanceClocks(base::TimeDelta::FromMilliseconds(3));
279  cast_environment_->Logging()->InsertPacketEvent(
280      receiver_clock_.NowTicks(),
281      PACKET_RECEIVED, VIDEO_EVENT,
282      rtp_timestamp_c,
283      frame_id_c,
284      56, 78, 1500);
285
286  cast_environment_->Logging()->InsertFrameEvent(
287      receiver_clock_.NowTicks(), FRAME_ACK_SENT, VIDEO_EVENT,
288      rtp_timestamp_c, frame_id_c);
289
290  AdvanceClocks(base::TimeDelta::FromMilliseconds(30));
291  cast_environment_->Logging()->InsertFrameEvent(sender_clock_->NowTicks(),
292                                                 FRAME_ACK_RECEIVED,
293                                                 VIDEO_EVENT,
294                                                 rtp_timestamp_c,
295                                                 frame_id_c);
296
297  EXPECT_TRUE(estimator_.GetReceiverOffsetBounds(&lower_bound, &upper_bound));
298  int64 lower_bound_ms = lower_bound.InMilliseconds();
299  int64 upper_bound_ms = upper_bound.InMilliseconds();
300  EXPECT_GT(lower_bound_ms, 90);
301  EXPECT_LE(lower_bound_ms, true_offset_ms);
302  EXPECT_LT(upper_bound_ms, 150);
303  EXPECT_GT(upper_bound_ms, true_offset_ms);
304}
305
306}  // namespace cast
307}  // namespace media
308