blob: 770bbf6eebd56aced50f89d394bea406c8718cb1 [file] [log] [blame]
stefan@webrtc.org5f284982012-06-28 07:51:16 +00001/*
2 * Copyright (c) 2012 The WebRTC project authors. All Rights Reserved.
3 *
4 * Use of this source code is governed by a BSD-style license
5 * that can be found in the LICENSE file in the root of the source
6 * tree. An additional intellectual property rights grant can be found
7 * in the file PATENTS. All contributing project authors may
8 * be found in the AUTHORS file in the root of the source tree.
9 */
10
pbos@webrtc.orgf5d4cb12013-05-17 13:44:48 +000011#include <math.h>
stefan@webrtc.org5f284982012-06-28 07:51:16 +000012
kjellander@webrtc.org0fcaf992015-11-26 15:24:52 +010013#include <algorithm>
14
kwiberg77eab702016-09-28 17:42:01 -070015#include "webrtc/test/gtest.h"
Peter Boström7623ce42015-12-09 12:13:30 +010016#include "webrtc/video/stream_synchronization.h"
stefan@webrtc.org5f284982012-06-28 07:51:16 +000017
18namespace webrtc {
19
20// These correspond to the same constants defined in vie_sync_module.cc.
21enum { kMaxVideoDiffMs = 80 };
22enum { kMaxAudioDiffMs = 80 };
23enum { kMaxDelay = 1500 };
24
stefan@webrtc.org7c3523c2012-09-11 07:00:42 +000025// Test constants.
26enum { kDefaultAudioFrequency = 8000 };
27enum { kDefaultVideoFrequency = 90000 };
28const double kNtpFracPerMs = 4.294967296E6;
pwestin@webrtc.org63117332013-04-22 18:57:14 +000029static const int kSmoothingFilter = 4 * 2;
stefan@webrtc.org7c3523c2012-09-11 07:00:42 +000030
stefan@webrtc.org5f284982012-06-28 07:51:16 +000031class Time {
32 public:
33 explicit Time(int64_t offset)
34 : kNtpJan1970(2208988800UL),
35 time_now_ms_(offset) {}
36
wu@webrtc.org66773a02014-05-07 17:09:44 +000037 RtcpMeasurement GenerateRtcp(int frequency, uint32_t offset) const {
38 RtcpMeasurement rtcp;
asaperssonb7e7b492016-11-17 02:27:14 -080039 rtcp.ntp_time = GetNowNtp();
40 rtcp.rtp_timestamp = GetNowRtp(frequency, offset);
stefan@webrtc.org7c3523c2012-09-11 07:00:42 +000041 return rtcp;
42 }
43
asaperssonb7e7b492016-11-17 02:27:14 -080044 NtpTime GetNowNtp() const {
45 uint32_t ntp_secs = time_now_ms_ / 1000 + kNtpJan1970;
stefan@webrtc.org7c3523c2012-09-11 07:00:42 +000046 int64_t remainder_ms = time_now_ms_ % 1000;
asaperssonb7e7b492016-11-17 02:27:14 -080047 uint32_t ntp_frac = static_cast<uint32_t>(
stefan@webrtc.org7c3523c2012-09-11 07:00:42 +000048 static_cast<double>(remainder_ms) * kNtpFracPerMs + 0.5);
asaperssonb7e7b492016-11-17 02:27:14 -080049 return NtpTime(ntp_secs, ntp_frac);
stefan@webrtc.org7c3523c2012-09-11 07:00:42 +000050 }
51
asaperssonb7e7b492016-11-17 02:27:14 -080052 uint32_t GetNowRtp(int frequency, uint32_t offset) const {
stefan@webrtc.org7c3523c2012-09-11 07:00:42 +000053 return frequency * time_now_ms_ / 1000 + offset;
stefan@webrtc.org5f284982012-06-28 07:51:16 +000054 }
55
56 void IncreaseTimeMs(int64_t inc) {
57 time_now_ms_ += inc;
58 }
59
60 int64_t time_now_ms() const {
61 return time_now_ms_;
62 }
stefan@webrtc.org7c3523c2012-09-11 07:00:42 +000063
stefan@webrtc.org5f284982012-06-28 07:51:16 +000064 private:
65 // January 1970, in NTP seconds.
66 const uint32_t kNtpJan1970;
67 int64_t time_now_ms_;
68};
69
70class StreamSynchronizationTest : public ::testing::Test {
71 protected:
72 virtual void SetUp() {
73 sync_ = new StreamSynchronization(0, 0);
74 send_time_ = new Time(kSendTimeOffsetMs);
75 receive_time_ = new Time(kReceiveTimeOffsetMs);
stefan@webrtc.org7c3523c2012-09-11 07:00:42 +000076 audio_clock_drift_ = 1.0;
77 video_clock_drift_ = 1.0;
stefan@webrtc.org5f284982012-06-28 07:51:16 +000078 }
79
80 virtual void TearDown() {
81 delete sync_;
82 delete send_time_;
83 delete receive_time_;
84 }
85
stefan@webrtc.org7c3523c2012-09-11 07:00:42 +000086 // Generates the necessary RTCP measurements and RTP timestamps and computes
87 // the audio and video delays needed to get the two streams in sync.
88 // |audio_delay_ms| and |video_delay_ms| are the number of milliseconds after
89 // capture which the frames are rendered.
90 // |current_audio_delay_ms| is the number of milliseconds which audio is
91 // currently being delayed by the receiver.
92 bool DelayedStreams(int audio_delay_ms,
93 int video_delay_ms,
94 int current_audio_delay_ms,
95 int* extra_audio_delay_ms,
96 int* total_video_delay_ms) {
97 int audio_frequency = static_cast<int>(kDefaultAudioFrequency *
98 audio_clock_drift_ + 0.5);
99 int audio_offset = 0;
100 int video_frequency = static_cast<int>(kDefaultVideoFrequency *
101 video_clock_drift_ + 0.5);
asaperssonde9e5ff2016-11-02 07:14:03 -0700102 bool new_sr;
stefan@webrtc.org7c3523c2012-09-11 07:00:42 +0000103 int video_offset = 0;
stefan@webrtc.org5f284982012-06-28 07:51:16 +0000104 StreamSynchronization::Measurements audio;
105 StreamSynchronization::Measurements video;
stefan@webrtc.org7c3523c2012-09-11 07:00:42 +0000106 // Generate NTP/RTP timestamp pair for both streams corresponding to RTCP.
asaperssonde9e5ff2016-11-02 07:14:03 -0700107 RtcpMeasurement rtcp =
108 send_time_->GenerateRtcp(audio_frequency, audio_offset);
asaperssonb7e7b492016-11-17 02:27:14 -0800109 EXPECT_TRUE(UpdateRtcpList(rtcp.ntp_time.seconds(),
110 rtcp.ntp_time.fractions(), rtcp.rtp_timestamp,
asaperssonde9e5ff2016-11-02 07:14:03 -0700111 &audio.rtcp, &new_sr));
stefan@webrtc.org7c3523c2012-09-11 07:00:42 +0000112 send_time_->IncreaseTimeMs(100);
113 receive_time_->IncreaseTimeMs(100);
asaperssonde9e5ff2016-11-02 07:14:03 -0700114 rtcp = send_time_->GenerateRtcp(video_frequency, video_offset);
asaperssonb7e7b492016-11-17 02:27:14 -0800115 EXPECT_TRUE(UpdateRtcpList(rtcp.ntp_time.seconds(),
116 rtcp.ntp_time.fractions(), rtcp.rtp_timestamp,
asaperssonde9e5ff2016-11-02 07:14:03 -0700117 &video.rtcp, &new_sr));
stefan@webrtc.org7c3523c2012-09-11 07:00:42 +0000118 send_time_->IncreaseTimeMs(900);
119 receive_time_->IncreaseTimeMs(900);
asaperssonde9e5ff2016-11-02 07:14:03 -0700120 rtcp = send_time_->GenerateRtcp(audio_frequency, audio_offset);
asaperssonb7e7b492016-11-17 02:27:14 -0800121 EXPECT_TRUE(UpdateRtcpList(rtcp.ntp_time.seconds(),
122 rtcp.ntp_time.fractions(), rtcp.rtp_timestamp,
asaperssonde9e5ff2016-11-02 07:14:03 -0700123 &audio.rtcp, &new_sr));
stefan@webrtc.org7c3523c2012-09-11 07:00:42 +0000124 send_time_->IncreaseTimeMs(100);
125 receive_time_->IncreaseTimeMs(100);
asaperssonde9e5ff2016-11-02 07:14:03 -0700126 rtcp = send_time_->GenerateRtcp(video_frequency, video_offset);
asaperssonb7e7b492016-11-17 02:27:14 -0800127 EXPECT_TRUE(UpdateRtcpList(rtcp.ntp_time.seconds(),
128 rtcp.ntp_time.fractions(), rtcp.rtp_timestamp,
asaperssonde9e5ff2016-11-02 07:14:03 -0700129 &video.rtcp, &new_sr));
asaperssonb7e7b492016-11-17 02:27:14 -0800130
stefan@webrtc.org7c3523c2012-09-11 07:00:42 +0000131 send_time_->IncreaseTimeMs(900);
132 receive_time_->IncreaseTimeMs(900);
stefan@webrtc.org5f284982012-06-28 07:51:16 +0000133
stefan@webrtc.org7c3523c2012-09-11 07:00:42 +0000134 // Capture an audio and a video frame at the same time.
asaperssonb7e7b492016-11-17 02:27:14 -0800135 audio.latest_timestamp =
136 send_time_->GetNowRtp(audio_frequency, audio_offset);
137 video.latest_timestamp =
138 send_time_->GetNowRtp(video_frequency, video_offset);
stefan@webrtc.org5f284982012-06-28 07:51:16 +0000139
140 if (audio_delay_ms > video_delay_ms) {
141 // Audio later than video.
142 receive_time_->IncreaseTimeMs(video_delay_ms);
stefan@webrtc.org7c3523c2012-09-11 07:00:42 +0000143 video.latest_receive_time_ms = receive_time_->time_now_ms();
stefan@webrtc.org5f284982012-06-28 07:51:16 +0000144 receive_time_->IncreaseTimeMs(audio_delay_ms - video_delay_ms);
stefan@webrtc.org7c3523c2012-09-11 07:00:42 +0000145 audio.latest_receive_time_ms = receive_time_->time_now_ms();
stefan@webrtc.org5f284982012-06-28 07:51:16 +0000146 } else {
147 // Video later than audio.
148 receive_time_->IncreaseTimeMs(audio_delay_ms);
stefan@webrtc.org7c3523c2012-09-11 07:00:42 +0000149 audio.latest_receive_time_ms = receive_time_->time_now_ms();
stefan@webrtc.org5f284982012-06-28 07:51:16 +0000150 receive_time_->IncreaseTimeMs(video_delay_ms - audio_delay_ms);
stefan@webrtc.org7c3523c2012-09-11 07:00:42 +0000151 video.latest_receive_time_ms = receive_time_->time_now_ms();
stefan@webrtc.org5f284982012-06-28 07:51:16 +0000152 }
stefan@webrtc.org7c3523c2012-09-11 07:00:42 +0000153 int relative_delay_ms;
154 StreamSynchronization::ComputeRelativeDelay(audio, video,
155 &relative_delay_ms);
156 EXPECT_EQ(video_delay_ms - audio_delay_ms, relative_delay_ms);
157 return sync_->ComputeDelays(relative_delay_ms,
stefan@webrtc.org5f284982012-06-28 07:51:16 +0000158 current_audio_delay_ms,
159 extra_audio_delay_ms,
stefan@webrtc.org5f284982012-06-28 07:51:16 +0000160 total_video_delay_ms);
161 }
162
stefan@webrtc.org7c3523c2012-09-11 07:00:42 +0000163 // Simulate audio playback 300 ms after capture and video rendering 100 ms
164 // after capture. Verify that the correct extra delays are calculated for
165 // audio and video, and that they change correctly when we simulate that
166 // NetEQ or the VCM adds more delay to the streams.
167 // TODO(holmer): This is currently wrong! We should simply change
168 // audio_delay_ms or video_delay_ms since those now include VCM and NetEQ
169 // delays.
mikhal@webrtc.orgef9f76a2013-02-15 23:22:18 +0000170 void BothDelayedAudioLaterTest(int base_target_delay) {
171 int current_audio_delay_ms = base_target_delay;
172 int audio_delay_ms = base_target_delay + 300;
173 int video_delay_ms = base_target_delay + 100;
stefan@webrtc.org7c3523c2012-09-11 07:00:42 +0000174 int extra_audio_delay_ms = 0;
mikhal@webrtc.orgef9f76a2013-02-15 23:22:18 +0000175 int total_video_delay_ms = base_target_delay;
pwestin@webrtc.org63117332013-04-22 18:57:14 +0000176 int filtered_move = (audio_delay_ms - video_delay_ms) / kSmoothingFilter;
pwestin@webrtc.org4e545b32013-04-26 15:23:34 +0000177 const int kNeteqDelayIncrease = 50;
178 const int kNeteqDelayDecrease = 10;
stefan@webrtc.org7c3523c2012-09-11 07:00:42 +0000179
180 EXPECT_TRUE(DelayedStreams(audio_delay_ms,
181 video_delay_ms,
182 current_audio_delay_ms,
183 &extra_audio_delay_ms,
184 &total_video_delay_ms));
pwestin@webrtc.org63117332013-04-22 18:57:14 +0000185 EXPECT_EQ(base_target_delay + filtered_move, total_video_delay_ms);
mikhal@webrtc.orgef9f76a2013-02-15 23:22:18 +0000186 EXPECT_EQ(base_target_delay, extra_audio_delay_ms);
stefan@webrtc.org7c3523c2012-09-11 07:00:42 +0000187 current_audio_delay_ms = extra_audio_delay_ms;
188
189 send_time_->IncreaseTimeMs(1000);
190 receive_time_->IncreaseTimeMs(1000 - std::max(audio_delay_ms,
191 video_delay_ms));
mikhal@webrtc.orgef9f76a2013-02-15 23:22:18 +0000192 // Simulate base_target_delay minimum delay in the VCM.
193 total_video_delay_ms = base_target_delay;
stefan@webrtc.org7c3523c2012-09-11 07:00:42 +0000194 EXPECT_TRUE(DelayedStreams(audio_delay_ms,
195 video_delay_ms,
196 current_audio_delay_ms,
197 &extra_audio_delay_ms,
198 &total_video_delay_ms));
pwestin@webrtc.org63117332013-04-22 18:57:14 +0000199 EXPECT_EQ(base_target_delay + 2 * filtered_move, total_video_delay_ms);
mikhal@webrtc.orgef9f76a2013-02-15 23:22:18 +0000200 EXPECT_EQ(base_target_delay, extra_audio_delay_ms);
stefan@webrtc.org7c3523c2012-09-11 07:00:42 +0000201 current_audio_delay_ms = extra_audio_delay_ms;
202
203 send_time_->IncreaseTimeMs(1000);
204 receive_time_->IncreaseTimeMs(1000 - std::max(audio_delay_ms,
205 video_delay_ms));
mikhal@webrtc.orgef9f76a2013-02-15 23:22:18 +0000206 // Simulate base_target_delay minimum delay in the VCM.
207 total_video_delay_ms = base_target_delay;
stefan@webrtc.org7c3523c2012-09-11 07:00:42 +0000208 EXPECT_TRUE(DelayedStreams(audio_delay_ms,
209 video_delay_ms,
210 current_audio_delay_ms,
211 &extra_audio_delay_ms,
212 &total_video_delay_ms));
pwestin@webrtc.org63117332013-04-22 18:57:14 +0000213 EXPECT_EQ(base_target_delay + 3 * filtered_move, total_video_delay_ms);
mikhal@webrtc.orgef9f76a2013-02-15 23:22:18 +0000214 EXPECT_EQ(base_target_delay, extra_audio_delay_ms);
stefan@webrtc.org7c3523c2012-09-11 07:00:42 +0000215
216 // Simulate that NetEQ introduces some audio delay.
pwestin@webrtc.org4e545b32013-04-26 15:23:34 +0000217 current_audio_delay_ms = base_target_delay + kNeteqDelayIncrease;
stefan@webrtc.org7c3523c2012-09-11 07:00:42 +0000218 send_time_->IncreaseTimeMs(1000);
219 receive_time_->IncreaseTimeMs(1000 - std::max(audio_delay_ms,
220 video_delay_ms));
mikhal@webrtc.orgef9f76a2013-02-15 23:22:18 +0000221 // Simulate base_target_delay minimum delay in the VCM.
222 total_video_delay_ms = base_target_delay;
stefan@webrtc.org7c3523c2012-09-11 07:00:42 +0000223 EXPECT_TRUE(DelayedStreams(audio_delay_ms,
224 video_delay_ms,
225 current_audio_delay_ms,
226 &extra_audio_delay_ms,
227 &total_video_delay_ms));
pwestin@webrtc.org63117332013-04-22 18:57:14 +0000228 filtered_move = 3 * filtered_move +
pwestin@webrtc.org4e545b32013-04-26 15:23:34 +0000229 (kNeteqDelayIncrease + audio_delay_ms - video_delay_ms) /
230 kSmoothingFilter;
pwestin@webrtc.org63117332013-04-22 18:57:14 +0000231 EXPECT_EQ(base_target_delay + filtered_move, total_video_delay_ms);
mikhal@webrtc.orgef9f76a2013-02-15 23:22:18 +0000232 EXPECT_EQ(base_target_delay, extra_audio_delay_ms);
stefan@webrtc.org7c3523c2012-09-11 07:00:42 +0000233
234 // Simulate that NetEQ reduces its delay.
pwestin@webrtc.org4e545b32013-04-26 15:23:34 +0000235 current_audio_delay_ms = base_target_delay + kNeteqDelayDecrease;
stefan@webrtc.org7c3523c2012-09-11 07:00:42 +0000236 send_time_->IncreaseTimeMs(1000);
237 receive_time_->IncreaseTimeMs(1000 - std::max(audio_delay_ms,
238 video_delay_ms));
mikhal@webrtc.orgef9f76a2013-02-15 23:22:18 +0000239 // Simulate base_target_delay minimum delay in the VCM.
240 total_video_delay_ms = base_target_delay;
stefan@webrtc.org7c3523c2012-09-11 07:00:42 +0000241 EXPECT_TRUE(DelayedStreams(audio_delay_ms,
242 video_delay_ms,
243 current_audio_delay_ms,
244 &extra_audio_delay_ms,
245 &total_video_delay_ms));
pwestin@webrtc.org63117332013-04-22 18:57:14 +0000246
247 filtered_move = filtered_move +
pwestin@webrtc.org4e545b32013-04-26 15:23:34 +0000248 (kNeteqDelayDecrease + audio_delay_ms - video_delay_ms) /
249 kSmoothingFilter;
pwestin@webrtc.org63117332013-04-22 18:57:14 +0000250
251 EXPECT_EQ(base_target_delay + filtered_move, total_video_delay_ms);
mikhal@webrtc.orgef9f76a2013-02-15 23:22:18 +0000252 EXPECT_EQ(base_target_delay, extra_audio_delay_ms);
253 }
254
255 void BothDelayedVideoLaterTest(int base_target_delay) {
256 int current_audio_delay_ms = base_target_delay;
257 int audio_delay_ms = base_target_delay + 100;
258 int video_delay_ms = base_target_delay + 300;
259 int extra_audio_delay_ms = 0;
260 int total_video_delay_ms = base_target_delay;
261
262 EXPECT_TRUE(DelayedStreams(audio_delay_ms,
263 video_delay_ms,
264 current_audio_delay_ms,
265 &extra_audio_delay_ms,
266 &total_video_delay_ms));
267 EXPECT_EQ(base_target_delay, total_video_delay_ms);
268 // The audio delay is not allowed to change more than this in 1 second.
pwestin@webrtc.org63117332013-04-22 18:57:14 +0000269 EXPECT_GE(base_target_delay + kMaxAudioDiffMs, extra_audio_delay_ms);
mikhal@webrtc.orgef9f76a2013-02-15 23:22:18 +0000270 current_audio_delay_ms = extra_audio_delay_ms;
271 int current_extra_delay_ms = extra_audio_delay_ms;
272
273 send_time_->IncreaseTimeMs(1000);
274 receive_time_->IncreaseTimeMs(800);
275 EXPECT_TRUE(DelayedStreams(audio_delay_ms,
276 video_delay_ms,
277 current_audio_delay_ms,
278 &extra_audio_delay_ms,
279 &total_video_delay_ms));
280 EXPECT_EQ(base_target_delay, total_video_delay_ms);
281 // The audio delay is not allowed to change more than the half of the
282 // required change in delay.
283 EXPECT_EQ(current_extra_delay_ms + MaxAudioDelayIncrease(
284 current_audio_delay_ms,
285 base_target_delay + video_delay_ms - audio_delay_ms),
286 extra_audio_delay_ms);
287 current_audio_delay_ms = extra_audio_delay_ms;
288 current_extra_delay_ms = extra_audio_delay_ms;
289
290 send_time_->IncreaseTimeMs(1000);
291 receive_time_->IncreaseTimeMs(800);
292 EXPECT_TRUE(DelayedStreams(audio_delay_ms,
293 video_delay_ms,
294 current_audio_delay_ms,
295 &extra_audio_delay_ms,
296 &total_video_delay_ms));
297 EXPECT_EQ(base_target_delay, total_video_delay_ms);
298 // The audio delay is not allowed to change more than the half of the
299 // required change in delay.
300 EXPECT_EQ(current_extra_delay_ms + MaxAudioDelayIncrease(
301 current_audio_delay_ms,
302 base_target_delay + video_delay_ms - audio_delay_ms),
303 extra_audio_delay_ms);
304 current_extra_delay_ms = extra_audio_delay_ms;
305
306 // Simulate that NetEQ for some reason reduced the delay.
pwestin@webrtc.org63117332013-04-22 18:57:14 +0000307 current_audio_delay_ms = base_target_delay + 10;
mikhal@webrtc.orgef9f76a2013-02-15 23:22:18 +0000308 send_time_->IncreaseTimeMs(1000);
309 receive_time_->IncreaseTimeMs(800);
310 EXPECT_TRUE(DelayedStreams(audio_delay_ms,
311 video_delay_ms,
312 current_audio_delay_ms,
313 &extra_audio_delay_ms,
314 &total_video_delay_ms));
315 EXPECT_EQ(base_target_delay, total_video_delay_ms);
316 // Since we only can ask NetEQ for a certain amount of extra delay, and
317 // we only measure the total NetEQ delay, we will ask for additional delay
318 // here to try to stay in sync.
319 EXPECT_EQ(current_extra_delay_ms + MaxAudioDelayIncrease(
320 current_audio_delay_ms,
321 base_target_delay + video_delay_ms - audio_delay_ms),
322 extra_audio_delay_ms);
323 current_extra_delay_ms = extra_audio_delay_ms;
324
325 // Simulate that NetEQ for some reason significantly increased the delay.
pwestin@webrtc.org63117332013-04-22 18:57:14 +0000326 current_audio_delay_ms = base_target_delay + 350;
mikhal@webrtc.orgef9f76a2013-02-15 23:22:18 +0000327 send_time_->IncreaseTimeMs(1000);
328 receive_time_->IncreaseTimeMs(800);
329 EXPECT_TRUE(DelayedStreams(audio_delay_ms,
330 video_delay_ms,
331 current_audio_delay_ms,
332 &extra_audio_delay_ms,
333 &total_video_delay_ms));
334 EXPECT_EQ(base_target_delay, total_video_delay_ms);
335 // The audio delay is not allowed to change more than the half of the
336 // required change in delay.
337 EXPECT_EQ(current_extra_delay_ms + MaxAudioDelayIncrease(
338 current_audio_delay_ms,
339 base_target_delay + video_delay_ms - audio_delay_ms),
340 extra_audio_delay_ms);
stefan@webrtc.org7c3523c2012-09-11 07:00:42 +0000341 }
342
stefan@webrtc.org5f284982012-06-28 07:51:16 +0000343 int MaxAudioDelayIncrease(int current_audio_delay_ms, int delay_ms) {
pwestin@webrtc.org63117332013-04-22 18:57:14 +0000344 return std::min((delay_ms - current_audio_delay_ms) / kSmoothingFilter,
mikhal@webrtc.orgef9f76a2013-02-15 23:22:18 +0000345 static_cast<int>(kMaxAudioDiffMs));
stefan@webrtc.org5f284982012-06-28 07:51:16 +0000346 }
347
348 int MaxAudioDelayDecrease(int current_audio_delay_ms, int delay_ms) {
pwestin@webrtc.org63117332013-04-22 18:57:14 +0000349 return std::max((delay_ms - current_audio_delay_ms) / kSmoothingFilter,
350 -kMaxAudioDiffMs);
stefan@webrtc.org5f284982012-06-28 07:51:16 +0000351 }
352
stefan@webrtc.org7c3523c2012-09-11 07:00:42 +0000353 enum { kSendTimeOffsetMs = 98765 };
354 enum { kReceiveTimeOffsetMs = 43210 };
stefan@webrtc.org5f284982012-06-28 07:51:16 +0000355
356 StreamSynchronization* sync_;
stefan@webrtc.org7c3523c2012-09-11 07:00:42 +0000357 Time* send_time_; // The simulated clock at the sender.
358 Time* receive_time_; // The simulated clock at the receiver.
359 double audio_clock_drift_;
360 double video_clock_drift_;
stefan@webrtc.org5f284982012-06-28 07:51:16 +0000361};
362
363TEST_F(StreamSynchronizationTest, NoDelay) {
364 uint32_t current_audio_delay_ms = 0;
stefan@webrtc.org5f284982012-06-28 07:51:16 +0000365 int extra_audio_delay_ms = 0;
366 int total_video_delay_ms = 0;
367
pwestin@webrtc.org63117332013-04-22 18:57:14 +0000368 EXPECT_FALSE(DelayedStreams(0, 0, current_audio_delay_ms,
369 &extra_audio_delay_ms, &total_video_delay_ms));
stefan@webrtc.org5f284982012-06-28 07:51:16 +0000370 EXPECT_EQ(0, extra_audio_delay_ms);
371 EXPECT_EQ(0, total_video_delay_ms);
372}
373
374TEST_F(StreamSynchronizationTest, VideoDelay) {
375 uint32_t current_audio_delay_ms = 0;
376 int delay_ms = 200;
377 int extra_audio_delay_ms = 0;
378 int total_video_delay_ms = 0;
379
stefan@webrtc.org7c3523c2012-09-11 07:00:42 +0000380 EXPECT_TRUE(DelayedStreams(delay_ms, 0, current_audio_delay_ms,
381 &extra_audio_delay_ms, &total_video_delay_ms));
stefan@webrtc.org5f284982012-06-28 07:51:16 +0000382 EXPECT_EQ(0, extra_audio_delay_ms);
383 // The video delay is not allowed to change more than this in 1 second.
pwestin@webrtc.org63117332013-04-22 18:57:14 +0000384 EXPECT_EQ(delay_ms / kSmoothingFilter, total_video_delay_ms);
stefan@webrtc.org5f284982012-06-28 07:51:16 +0000385
386 send_time_->IncreaseTimeMs(1000);
387 receive_time_->IncreaseTimeMs(800);
388 // Simulate 0 minimum delay in the VCM.
389 total_video_delay_ms = 0;
stefan@webrtc.org7c3523c2012-09-11 07:00:42 +0000390 EXPECT_TRUE(DelayedStreams(delay_ms, 0, current_audio_delay_ms,
391 &extra_audio_delay_ms, &total_video_delay_ms));
stefan@webrtc.org5f284982012-06-28 07:51:16 +0000392 EXPECT_EQ(0, extra_audio_delay_ms);
393 // The video delay is not allowed to change more than this in 1 second.
pwestin@webrtc.org63117332013-04-22 18:57:14 +0000394 EXPECT_EQ(2 * delay_ms / kSmoothingFilter, total_video_delay_ms);
stefan@webrtc.org5f284982012-06-28 07:51:16 +0000395
396 send_time_->IncreaseTimeMs(1000);
397 receive_time_->IncreaseTimeMs(800);
398 // Simulate 0 minimum delay in the VCM.
399 total_video_delay_ms = 0;
stefan@webrtc.org7c3523c2012-09-11 07:00:42 +0000400 EXPECT_TRUE(DelayedStreams(delay_ms, 0, current_audio_delay_ms,
401 &extra_audio_delay_ms, &total_video_delay_ms));
stefan@webrtc.org5f284982012-06-28 07:51:16 +0000402 EXPECT_EQ(0, extra_audio_delay_ms);
pwestin@webrtc.org63117332013-04-22 18:57:14 +0000403 EXPECT_EQ(3 * delay_ms / kSmoothingFilter, total_video_delay_ms);
stefan@webrtc.org5f284982012-06-28 07:51:16 +0000404}
405
406TEST_F(StreamSynchronizationTest, AudioDelay) {
407 int current_audio_delay_ms = 0;
408 int delay_ms = 200;
409 int extra_audio_delay_ms = 0;
stefan@webrtc.org5f284982012-06-28 07:51:16 +0000410 int total_video_delay_ms = 0;
411
stefan@webrtc.org7c3523c2012-09-11 07:00:42 +0000412 EXPECT_TRUE(DelayedStreams(0, delay_ms, current_audio_delay_ms,
413 &extra_audio_delay_ms, &total_video_delay_ms));
stefan@webrtc.org5f284982012-06-28 07:51:16 +0000414 EXPECT_EQ(0, total_video_delay_ms);
415 // The audio delay is not allowed to change more than this in 1 second.
pwestin@webrtc.org63117332013-04-22 18:57:14 +0000416 EXPECT_EQ(delay_ms / kSmoothingFilter, extra_audio_delay_ms);
stefan@webrtc.org5f284982012-06-28 07:51:16 +0000417 current_audio_delay_ms = extra_audio_delay_ms;
andrew@webrtc.orgd7a71d02012-08-01 01:40:02 +0000418 int current_extra_delay_ms = extra_audio_delay_ms;
stefan@webrtc.org5f284982012-06-28 07:51:16 +0000419
420 send_time_->IncreaseTimeMs(1000);
421 receive_time_->IncreaseTimeMs(800);
stefan@webrtc.org7c3523c2012-09-11 07:00:42 +0000422 EXPECT_TRUE(DelayedStreams(0, delay_ms, current_audio_delay_ms,
423 &extra_audio_delay_ms, &total_video_delay_ms));
stefan@webrtc.org5f284982012-06-28 07:51:16 +0000424 EXPECT_EQ(0, total_video_delay_ms);
425 // The audio delay is not allowed to change more than the half of the required
426 // change in delay.
427 EXPECT_EQ(current_extra_delay_ms +
428 MaxAudioDelayIncrease(current_audio_delay_ms, delay_ms),
429 extra_audio_delay_ms);
430 current_audio_delay_ms = extra_audio_delay_ms;
431 current_extra_delay_ms = extra_audio_delay_ms;
432
433 send_time_->IncreaseTimeMs(1000);
434 receive_time_->IncreaseTimeMs(800);
stefan@webrtc.org7c3523c2012-09-11 07:00:42 +0000435 EXPECT_TRUE(DelayedStreams(0, delay_ms, current_audio_delay_ms,
436 &extra_audio_delay_ms, &total_video_delay_ms));
stefan@webrtc.org5f284982012-06-28 07:51:16 +0000437 EXPECT_EQ(0, total_video_delay_ms);
438 // The audio delay is not allowed to change more than the half of the required
439 // change in delay.
440 EXPECT_EQ(current_extra_delay_ms +
441 MaxAudioDelayIncrease(current_audio_delay_ms, delay_ms),
442 extra_audio_delay_ms);
443 current_extra_delay_ms = extra_audio_delay_ms;
444
445 // Simulate that NetEQ for some reason reduced the delay.
pwestin@webrtc.org63117332013-04-22 18:57:14 +0000446 current_audio_delay_ms = 10;
stefan@webrtc.org5f284982012-06-28 07:51:16 +0000447 send_time_->IncreaseTimeMs(1000);
448 receive_time_->IncreaseTimeMs(800);
stefan@webrtc.org7c3523c2012-09-11 07:00:42 +0000449 EXPECT_TRUE(DelayedStreams(0, delay_ms, current_audio_delay_ms,
450 &extra_audio_delay_ms, &total_video_delay_ms));
stefan@webrtc.org5f284982012-06-28 07:51:16 +0000451 EXPECT_EQ(0, total_video_delay_ms);
452 // Since we only can ask NetEQ for a certain amount of extra delay, and
453 // we only measure the total NetEQ delay, we will ask for additional delay
454 // here to try to
455 EXPECT_EQ(current_extra_delay_ms +
456 MaxAudioDelayIncrease(current_audio_delay_ms, delay_ms),
457 extra_audio_delay_ms);
458 current_extra_delay_ms = extra_audio_delay_ms;
459
460 // Simulate that NetEQ for some reason significantly increased the delay.
pwestin@webrtc.org63117332013-04-22 18:57:14 +0000461 current_audio_delay_ms = 350;
stefan@webrtc.org5f284982012-06-28 07:51:16 +0000462 send_time_->IncreaseTimeMs(1000);
463 receive_time_->IncreaseTimeMs(800);
stefan@webrtc.org7c3523c2012-09-11 07:00:42 +0000464 EXPECT_TRUE(DelayedStreams(0, delay_ms, current_audio_delay_ms,
465 &extra_audio_delay_ms, &total_video_delay_ms));
stefan@webrtc.org5f284982012-06-28 07:51:16 +0000466 EXPECT_EQ(0, total_video_delay_ms);
467 // The audio delay is not allowed to change more than the half of the required
468 // change in delay.
469 EXPECT_EQ(current_extra_delay_ms +
470 MaxAudioDelayDecrease(current_audio_delay_ms, delay_ms),
471 extra_audio_delay_ms);
472}
473
474TEST_F(StreamSynchronizationTest, BothDelayedVideoLater) {
mikhal@webrtc.orgef9f76a2013-02-15 23:22:18 +0000475 BothDelayedVideoLaterTest(0);
476}
stefan@webrtc.org5f284982012-06-28 07:51:16 +0000477
mikhal@webrtc.orgef9f76a2013-02-15 23:22:18 +0000478TEST_F(StreamSynchronizationTest, BothDelayedVideoLaterAudioClockDrift) {
479 audio_clock_drift_ = 1.05;
480 BothDelayedVideoLaterTest(0);
481}
stefan@webrtc.org5f284982012-06-28 07:51:16 +0000482
mikhal@webrtc.orgef9f76a2013-02-15 23:22:18 +0000483TEST_F(StreamSynchronizationTest, BothDelayedVideoLaterVideoClockDrift) {
484 video_clock_drift_ = 1.05;
485 BothDelayedVideoLaterTest(0);
stefan@webrtc.org5f284982012-06-28 07:51:16 +0000486}
487
488TEST_F(StreamSynchronizationTest, BothDelayedAudioLater) {
mikhal@webrtc.orgef9f76a2013-02-15 23:22:18 +0000489 BothDelayedAudioLaterTest(0);
stefan@webrtc.org7c3523c2012-09-11 07:00:42 +0000490}
stefan@webrtc.org5f284982012-06-28 07:51:16 +0000491
stefan@webrtc.org7c3523c2012-09-11 07:00:42 +0000492TEST_F(StreamSynchronizationTest, BothDelayedAudioClockDrift) {
493 audio_clock_drift_ = 1.05;
mikhal@webrtc.orgef9f76a2013-02-15 23:22:18 +0000494 BothDelayedAudioLaterTest(0);
stefan@webrtc.org7c3523c2012-09-11 07:00:42 +0000495}
stefan@webrtc.org5f284982012-06-28 07:51:16 +0000496
stefan@webrtc.org7c3523c2012-09-11 07:00:42 +0000497TEST_F(StreamSynchronizationTest, BothDelayedVideoClockDrift) {
498 video_clock_drift_ = 1.05;
mikhal@webrtc.orgef9f76a2013-02-15 23:22:18 +0000499 BothDelayedAudioLaterTest(0);
stefan@webrtc.org7c3523c2012-09-11 07:00:42 +0000500}
mikhal@webrtc.orgef9f76a2013-02-15 23:22:18 +0000501
502TEST_F(StreamSynchronizationTest, BaseDelay) {
503 int base_target_delay_ms = 2000;
504 int current_audio_delay_ms = 2000;
505 int extra_audio_delay_ms = 0;
506 int total_video_delay_ms = base_target_delay_ms;
507 sync_->SetTargetBufferingDelay(base_target_delay_ms);
pwestin@webrtc.org63117332013-04-22 18:57:14 +0000508 // We are in sync don't change.
509 EXPECT_FALSE(DelayedStreams(base_target_delay_ms, base_target_delay_ms,
510 current_audio_delay_ms,
511 &extra_audio_delay_ms, &total_video_delay_ms));
mikhal@webrtc.org0d8d0102013-02-22 19:30:44 +0000512 // Triggering another call with the same values. Delay should not be modified.
513 base_target_delay_ms = 2000;
514 current_audio_delay_ms = base_target_delay_ms;
515 total_video_delay_ms = base_target_delay_ms;
516 sync_->SetTargetBufferingDelay(base_target_delay_ms);
pwestin@webrtc.org63117332013-04-22 18:57:14 +0000517 // We are in sync don't change.
518 EXPECT_FALSE(DelayedStreams(base_target_delay_ms, base_target_delay_ms,
519 current_audio_delay_ms,
520 &extra_audio_delay_ms, &total_video_delay_ms));
mikhal@webrtc.org0d8d0102013-02-22 19:30:44 +0000521 // Changing delay value - intended to test this module only. In practice it
522 // would take VoE time to adapt.
523 base_target_delay_ms = 5000;
524 current_audio_delay_ms = base_target_delay_ms;
525 total_video_delay_ms = base_target_delay_ms;
526 sync_->SetTargetBufferingDelay(base_target_delay_ms);
pwestin@webrtc.org63117332013-04-22 18:57:14 +0000527 // We are in sync don't change.
528 EXPECT_FALSE(DelayedStreams(base_target_delay_ms, base_target_delay_ms,
529 current_audio_delay_ms,
530 &extra_audio_delay_ms, &total_video_delay_ms));
mikhal@webrtc.orgef9f76a2013-02-15 23:22:18 +0000531}
532
533TEST_F(StreamSynchronizationTest, BothDelayedAudioLaterWithBaseDelay) {
534 int base_target_delay_ms = 3000;
535 sync_->SetTargetBufferingDelay(base_target_delay_ms);
536 BothDelayedAudioLaterTest(base_target_delay_ms);
537}
538
539TEST_F(StreamSynchronizationTest, BothDelayedAudioClockDriftWithBaseDelay) {
540 int base_target_delay_ms = 3000;
541 sync_->SetTargetBufferingDelay(base_target_delay_ms);
542 audio_clock_drift_ = 1.05;
543 BothDelayedAudioLaterTest(base_target_delay_ms);
544}
545
546TEST_F(StreamSynchronizationTest, BothDelayedVideoClockDriftWithBaseDelay) {
547 int base_target_delay_ms = 3000;
548 sync_->SetTargetBufferingDelay(base_target_delay_ms);
549 video_clock_drift_ = 1.05;
550 BothDelayedAudioLaterTest(base_target_delay_ms);
551}
552
553TEST_F(StreamSynchronizationTest, BothDelayedVideoLaterWithBaseDelay) {
554 int base_target_delay_ms = 2000;
555 sync_->SetTargetBufferingDelay(base_target_delay_ms);
556 BothDelayedVideoLaterTest(base_target_delay_ms);
557}
558
559TEST_F(StreamSynchronizationTest,
560 BothDelayedVideoLaterAudioClockDriftWithBaseDelay) {
561 int base_target_delay_ms = 2000;
562 audio_clock_drift_ = 1.05;
563 sync_->SetTargetBufferingDelay(base_target_delay_ms);
564 BothDelayedVideoLaterTest(base_target_delay_ms);
565}
566
567TEST_F(StreamSynchronizationTest,
568 BothDelayedVideoLaterVideoClockDriftWithBaseDelay) {
569 int base_target_delay_ms = 2000;
570 video_clock_drift_ = 1.05;
571 sync_->SetTargetBufferingDelay(base_target_delay_ms);
572 BothDelayedVideoLaterTest(base_target_delay_ms);
573}
574
stefan@webrtc.org5f284982012-06-28 07:51:16 +0000575} // namespace webrtc