blob: cbd00e894388dbab6bccb86d5f69deaddb16486b [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
Jonas Olssona4d87372019-07-05 19:08:33 +020011#include "video/stream_synchronization.h"
12
kjellander@webrtc.org0fcaf992015-11-26 15:24:52 +010013#include <algorithm>
14
Yves Gerey3e707812018-11-28 16:47:49 +010015#include "system_wrappers/include/ntp_time.h"
Mirko Bonadei92ea95e2017-09-15 06:47:31 +020016#include "test/gtest.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)
Yves Gerey665174f2018-06-19 15:03:05 +020034 : kNtpJan1970(2208988800UL), time_now_ms_(offset) {}
stefan@webrtc.org5f284982012-06-28 07:51:16 +000035
asaperssonb7e7b492016-11-17 02:27:14 -080036 NtpTime GetNowNtp() const {
37 uint32_t ntp_secs = time_now_ms_ / 1000 + kNtpJan1970;
stefan@webrtc.org7c3523c2012-09-11 07:00:42 +000038 int64_t remainder_ms = time_now_ms_ % 1000;
asaperssonb7e7b492016-11-17 02:27:14 -080039 uint32_t ntp_frac = static_cast<uint32_t>(
stefan@webrtc.org7c3523c2012-09-11 07:00:42 +000040 static_cast<double>(remainder_ms) * kNtpFracPerMs + 0.5);
asaperssonb7e7b492016-11-17 02:27:14 -080041 return NtpTime(ntp_secs, ntp_frac);
stefan@webrtc.org7c3523c2012-09-11 07:00:42 +000042 }
43
asaperssonb7e7b492016-11-17 02:27:14 -080044 uint32_t GetNowRtp(int frequency, uint32_t offset) const {
stefan@webrtc.org7c3523c2012-09-11 07:00:42 +000045 return frequency * time_now_ms_ / 1000 + offset;
stefan@webrtc.org5f284982012-06-28 07:51:16 +000046 }
47
Yves Gerey665174f2018-06-19 15:03:05 +020048 void IncreaseTimeMs(int64_t inc) { time_now_ms_ += inc; }
stefan@webrtc.org5f284982012-06-28 07:51:16 +000049
Yves Gerey665174f2018-06-19 15:03:05 +020050 int64_t time_now_ms() const { return time_now_ms_; }
stefan@webrtc.org7c3523c2012-09-11 07:00:42 +000051
stefan@webrtc.org5f284982012-06-28 07:51:16 +000052 private:
53 // January 1970, in NTP seconds.
54 const uint32_t kNtpJan1970;
55 int64_t time_now_ms_;
56};
57
58class StreamSynchronizationTest : public ::testing::Test {
59 protected:
60 virtual void SetUp() {
61 sync_ = new StreamSynchronization(0, 0);
62 send_time_ = new Time(kSendTimeOffsetMs);
63 receive_time_ = new Time(kReceiveTimeOffsetMs);
stefan@webrtc.org7c3523c2012-09-11 07:00:42 +000064 audio_clock_drift_ = 1.0;
65 video_clock_drift_ = 1.0;
stefan@webrtc.org5f284982012-06-28 07:51:16 +000066 }
67
68 virtual void TearDown() {
69 delete sync_;
70 delete send_time_;
71 delete receive_time_;
72 }
73
stefan@webrtc.org7c3523c2012-09-11 07:00:42 +000074 // Generates the necessary RTCP measurements and RTP timestamps and computes
75 // the audio and video delays needed to get the two streams in sync.
76 // |audio_delay_ms| and |video_delay_ms| are the number of milliseconds after
77 // capture which the frames are rendered.
78 // |current_audio_delay_ms| is the number of milliseconds which audio is
79 // currently being delayed by the receiver.
80 bool DelayedStreams(int audio_delay_ms,
81 int video_delay_ms,
82 int current_audio_delay_ms,
83 int* extra_audio_delay_ms,
84 int* total_video_delay_ms) {
Yves Gerey665174f2018-06-19 15:03:05 +020085 int audio_frequency =
86 static_cast<int>(kDefaultAudioFrequency * audio_clock_drift_ + 0.5);
stefan@webrtc.org7c3523c2012-09-11 07:00:42 +000087 int audio_offset = 0;
Yves Gerey665174f2018-06-19 15:03:05 +020088 int video_frequency =
89 static_cast<int>(kDefaultVideoFrequency * video_clock_drift_ + 0.5);
asaperssonde9e5ff2016-11-02 07:14:03 -070090 bool new_sr;
stefan@webrtc.org7c3523c2012-09-11 07:00:42 +000091 int video_offset = 0;
stefan@webrtc.org5f284982012-06-28 07:51:16 +000092 StreamSynchronization::Measurements audio;
93 StreamSynchronization::Measurements video;
stefan@webrtc.org7c3523c2012-09-11 07:00:42 +000094 // Generate NTP/RTP timestamp pair for both streams corresponding to RTCP.
asaperssonfe50b4d2016-12-22 07:53:51 -080095 NtpTime ntp_time = send_time_->GetNowNtp();
96 uint32_t rtp_timestamp =
97 send_time_->GetNowRtp(audio_frequency, audio_offset);
98 EXPECT_TRUE(audio.rtp_to_ntp.UpdateMeasurements(
99 ntp_time.seconds(), ntp_time.fractions(), rtp_timestamp, &new_sr));
stefan@webrtc.org7c3523c2012-09-11 07:00:42 +0000100 send_time_->IncreaseTimeMs(100);
101 receive_time_->IncreaseTimeMs(100);
asaperssonfe50b4d2016-12-22 07:53:51 -0800102 ntp_time = send_time_->GetNowNtp();
103 rtp_timestamp = send_time_->GetNowRtp(video_frequency, video_offset);
104 EXPECT_TRUE(video.rtp_to_ntp.UpdateMeasurements(
105 ntp_time.seconds(), ntp_time.fractions(), rtp_timestamp, &new_sr));
stefan@webrtc.org7c3523c2012-09-11 07:00:42 +0000106 send_time_->IncreaseTimeMs(900);
107 receive_time_->IncreaseTimeMs(900);
asaperssonfe50b4d2016-12-22 07:53:51 -0800108 ntp_time = send_time_->GetNowNtp();
109 rtp_timestamp = send_time_->GetNowRtp(audio_frequency, audio_offset);
110 EXPECT_TRUE(audio.rtp_to_ntp.UpdateMeasurements(
111 ntp_time.seconds(), ntp_time.fractions(), rtp_timestamp, &new_sr));
stefan@webrtc.org7c3523c2012-09-11 07:00:42 +0000112 send_time_->IncreaseTimeMs(100);
113 receive_time_->IncreaseTimeMs(100);
asaperssonfe50b4d2016-12-22 07:53:51 -0800114 ntp_time = send_time_->GetNowNtp();
115 rtp_timestamp = send_time_->GetNowRtp(video_frequency, video_offset);
116 EXPECT_TRUE(video.rtp_to_ntp.UpdateMeasurements(
117 ntp_time.seconds(), ntp_time.fractions(), rtp_timestamp, &new_sr));
asaperssonb7e7b492016-11-17 02:27:14 -0800118
stefan@webrtc.org7c3523c2012-09-11 07:00:42 +0000119 send_time_->IncreaseTimeMs(900);
120 receive_time_->IncreaseTimeMs(900);
stefan@webrtc.org5f284982012-06-28 07:51:16 +0000121
stefan@webrtc.org7c3523c2012-09-11 07:00:42 +0000122 // Capture an audio and a video frame at the same time.
asaperssonb7e7b492016-11-17 02:27:14 -0800123 audio.latest_timestamp =
124 send_time_->GetNowRtp(audio_frequency, audio_offset);
125 video.latest_timestamp =
126 send_time_->GetNowRtp(video_frequency, video_offset);
stefan@webrtc.org5f284982012-06-28 07:51:16 +0000127
128 if (audio_delay_ms > video_delay_ms) {
129 // Audio later than video.
130 receive_time_->IncreaseTimeMs(video_delay_ms);
stefan@webrtc.org7c3523c2012-09-11 07:00:42 +0000131 video.latest_receive_time_ms = receive_time_->time_now_ms();
stefan@webrtc.org5f284982012-06-28 07:51:16 +0000132 receive_time_->IncreaseTimeMs(audio_delay_ms - video_delay_ms);
stefan@webrtc.org7c3523c2012-09-11 07:00:42 +0000133 audio.latest_receive_time_ms = receive_time_->time_now_ms();
stefan@webrtc.org5f284982012-06-28 07:51:16 +0000134 } else {
135 // Video later than audio.
136 receive_time_->IncreaseTimeMs(audio_delay_ms);
stefan@webrtc.org7c3523c2012-09-11 07:00:42 +0000137 audio.latest_receive_time_ms = receive_time_->time_now_ms();
stefan@webrtc.org5f284982012-06-28 07:51:16 +0000138 receive_time_->IncreaseTimeMs(video_delay_ms - audio_delay_ms);
stefan@webrtc.org7c3523c2012-09-11 07:00:42 +0000139 video.latest_receive_time_ms = receive_time_->time_now_ms();
stefan@webrtc.org5f284982012-06-28 07:51:16 +0000140 }
stefan@webrtc.org7c3523c2012-09-11 07:00:42 +0000141 int relative_delay_ms;
142 StreamSynchronization::ComputeRelativeDelay(audio, video,
143 &relative_delay_ms);
144 EXPECT_EQ(video_delay_ms - audio_delay_ms, relative_delay_ms);
Yves Gerey665174f2018-06-19 15:03:05 +0200145 return sync_->ComputeDelays(relative_delay_ms, current_audio_delay_ms,
146 extra_audio_delay_ms, total_video_delay_ms);
stefan@webrtc.org5f284982012-06-28 07:51:16 +0000147 }
148
stefan@webrtc.org7c3523c2012-09-11 07:00:42 +0000149 // Simulate audio playback 300 ms after capture and video rendering 100 ms
150 // after capture. Verify that the correct extra delays are calculated for
151 // audio and video, and that they change correctly when we simulate that
152 // NetEQ or the VCM adds more delay to the streams.
153 // TODO(holmer): This is currently wrong! We should simply change
154 // audio_delay_ms or video_delay_ms since those now include VCM and NetEQ
155 // delays.
mikhal@webrtc.orgef9f76a2013-02-15 23:22:18 +0000156 void BothDelayedAudioLaterTest(int base_target_delay) {
157 int current_audio_delay_ms = base_target_delay;
158 int audio_delay_ms = base_target_delay + 300;
159 int video_delay_ms = base_target_delay + 100;
stefan@webrtc.org7c3523c2012-09-11 07:00:42 +0000160 int extra_audio_delay_ms = 0;
mikhal@webrtc.orgef9f76a2013-02-15 23:22:18 +0000161 int total_video_delay_ms = base_target_delay;
pwestin@webrtc.org63117332013-04-22 18:57:14 +0000162 int filtered_move = (audio_delay_ms - video_delay_ms) / kSmoothingFilter;
pwestin@webrtc.org4e545b32013-04-26 15:23:34 +0000163 const int kNeteqDelayIncrease = 50;
164 const int kNeteqDelayDecrease = 10;
stefan@webrtc.org7c3523c2012-09-11 07:00:42 +0000165
Yves Gerey665174f2018-06-19 15:03:05 +0200166 EXPECT_TRUE(DelayedStreams(audio_delay_ms, video_delay_ms,
167 current_audio_delay_ms, &extra_audio_delay_ms,
stefan@webrtc.org7c3523c2012-09-11 07:00:42 +0000168 &total_video_delay_ms));
pwestin@webrtc.org63117332013-04-22 18:57:14 +0000169 EXPECT_EQ(base_target_delay + filtered_move, total_video_delay_ms);
mikhal@webrtc.orgef9f76a2013-02-15 23:22:18 +0000170 EXPECT_EQ(base_target_delay, extra_audio_delay_ms);
stefan@webrtc.org7c3523c2012-09-11 07:00:42 +0000171 current_audio_delay_ms = extra_audio_delay_ms;
172
173 send_time_->IncreaseTimeMs(1000);
Yves Gerey665174f2018-06-19 15:03:05 +0200174 receive_time_->IncreaseTimeMs(1000 -
175 std::max(audio_delay_ms, video_delay_ms));
mikhal@webrtc.orgef9f76a2013-02-15 23:22:18 +0000176 // Simulate base_target_delay minimum delay in the VCM.
177 total_video_delay_ms = base_target_delay;
Yves Gerey665174f2018-06-19 15:03:05 +0200178 EXPECT_TRUE(DelayedStreams(audio_delay_ms, video_delay_ms,
179 current_audio_delay_ms, &extra_audio_delay_ms,
stefan@webrtc.org7c3523c2012-09-11 07:00:42 +0000180 &total_video_delay_ms));
pwestin@webrtc.org63117332013-04-22 18:57:14 +0000181 EXPECT_EQ(base_target_delay + 2 * filtered_move, total_video_delay_ms);
mikhal@webrtc.orgef9f76a2013-02-15 23:22:18 +0000182 EXPECT_EQ(base_target_delay, extra_audio_delay_ms);
stefan@webrtc.org7c3523c2012-09-11 07:00:42 +0000183 current_audio_delay_ms = extra_audio_delay_ms;
184
185 send_time_->IncreaseTimeMs(1000);
Yves Gerey665174f2018-06-19 15:03:05 +0200186 receive_time_->IncreaseTimeMs(1000 -
187 std::max(audio_delay_ms, video_delay_ms));
mikhal@webrtc.orgef9f76a2013-02-15 23:22:18 +0000188 // Simulate base_target_delay minimum delay in the VCM.
189 total_video_delay_ms = base_target_delay;
Yves Gerey665174f2018-06-19 15:03:05 +0200190 EXPECT_TRUE(DelayedStreams(audio_delay_ms, video_delay_ms,
191 current_audio_delay_ms, &extra_audio_delay_ms,
stefan@webrtc.org7c3523c2012-09-11 07:00:42 +0000192 &total_video_delay_ms));
pwestin@webrtc.org63117332013-04-22 18:57:14 +0000193 EXPECT_EQ(base_target_delay + 3 * filtered_move, total_video_delay_ms);
mikhal@webrtc.orgef9f76a2013-02-15 23:22:18 +0000194 EXPECT_EQ(base_target_delay, extra_audio_delay_ms);
stefan@webrtc.org7c3523c2012-09-11 07:00:42 +0000195
196 // Simulate that NetEQ introduces some audio delay.
pwestin@webrtc.org4e545b32013-04-26 15:23:34 +0000197 current_audio_delay_ms = base_target_delay + kNeteqDelayIncrease;
stefan@webrtc.org7c3523c2012-09-11 07:00:42 +0000198 send_time_->IncreaseTimeMs(1000);
Yves Gerey665174f2018-06-19 15:03:05 +0200199 receive_time_->IncreaseTimeMs(1000 -
200 std::max(audio_delay_ms, video_delay_ms));
mikhal@webrtc.orgef9f76a2013-02-15 23:22:18 +0000201 // Simulate base_target_delay minimum delay in the VCM.
202 total_video_delay_ms = base_target_delay;
Yves Gerey665174f2018-06-19 15:03:05 +0200203 EXPECT_TRUE(DelayedStreams(audio_delay_ms, video_delay_ms,
204 current_audio_delay_ms, &extra_audio_delay_ms,
stefan@webrtc.org7c3523c2012-09-11 07:00:42 +0000205 &total_video_delay_ms));
pwestin@webrtc.org63117332013-04-22 18:57:14 +0000206 filtered_move = 3 * filtered_move +
Yves Gerey665174f2018-06-19 15:03:05 +0200207 (kNeteqDelayIncrease + audio_delay_ms - video_delay_ms) /
208 kSmoothingFilter;
pwestin@webrtc.org63117332013-04-22 18:57:14 +0000209 EXPECT_EQ(base_target_delay + filtered_move, total_video_delay_ms);
mikhal@webrtc.orgef9f76a2013-02-15 23:22:18 +0000210 EXPECT_EQ(base_target_delay, extra_audio_delay_ms);
stefan@webrtc.org7c3523c2012-09-11 07:00:42 +0000211
212 // Simulate that NetEQ reduces its delay.
pwestin@webrtc.org4e545b32013-04-26 15:23:34 +0000213 current_audio_delay_ms = base_target_delay + kNeteqDelayDecrease;
stefan@webrtc.org7c3523c2012-09-11 07:00:42 +0000214 send_time_->IncreaseTimeMs(1000);
Yves Gerey665174f2018-06-19 15:03:05 +0200215 receive_time_->IncreaseTimeMs(1000 -
216 std::max(audio_delay_ms, video_delay_ms));
mikhal@webrtc.orgef9f76a2013-02-15 23:22:18 +0000217 // Simulate base_target_delay minimum delay in the VCM.
218 total_video_delay_ms = base_target_delay;
Yves Gerey665174f2018-06-19 15:03:05 +0200219 EXPECT_TRUE(DelayedStreams(audio_delay_ms, video_delay_ms,
220 current_audio_delay_ms, &extra_audio_delay_ms,
stefan@webrtc.org7c3523c2012-09-11 07:00:42 +0000221 &total_video_delay_ms));
pwestin@webrtc.org63117332013-04-22 18:57:14 +0000222
223 filtered_move = filtered_move +
Yves Gerey665174f2018-06-19 15:03:05 +0200224 (kNeteqDelayDecrease + audio_delay_ms - video_delay_ms) /
225 kSmoothingFilter;
pwestin@webrtc.org63117332013-04-22 18:57:14 +0000226
227 EXPECT_EQ(base_target_delay + filtered_move, total_video_delay_ms);
mikhal@webrtc.orgef9f76a2013-02-15 23:22:18 +0000228 EXPECT_EQ(base_target_delay, extra_audio_delay_ms);
229 }
230
231 void BothDelayedVideoLaterTest(int base_target_delay) {
232 int current_audio_delay_ms = base_target_delay;
233 int audio_delay_ms = base_target_delay + 100;
234 int video_delay_ms = base_target_delay + 300;
235 int extra_audio_delay_ms = 0;
236 int total_video_delay_ms = base_target_delay;
237
Yves Gerey665174f2018-06-19 15:03:05 +0200238 EXPECT_TRUE(DelayedStreams(audio_delay_ms, video_delay_ms,
239 current_audio_delay_ms, &extra_audio_delay_ms,
mikhal@webrtc.orgef9f76a2013-02-15 23:22:18 +0000240 &total_video_delay_ms));
241 EXPECT_EQ(base_target_delay, total_video_delay_ms);
242 // The audio delay is not allowed to change more than this in 1 second.
pwestin@webrtc.org63117332013-04-22 18:57:14 +0000243 EXPECT_GE(base_target_delay + kMaxAudioDiffMs, extra_audio_delay_ms);
mikhal@webrtc.orgef9f76a2013-02-15 23:22:18 +0000244 current_audio_delay_ms = extra_audio_delay_ms;
245 int current_extra_delay_ms = extra_audio_delay_ms;
246
247 send_time_->IncreaseTimeMs(1000);
248 receive_time_->IncreaseTimeMs(800);
Yves Gerey665174f2018-06-19 15:03:05 +0200249 EXPECT_TRUE(DelayedStreams(audio_delay_ms, video_delay_ms,
250 current_audio_delay_ms, &extra_audio_delay_ms,
mikhal@webrtc.orgef9f76a2013-02-15 23:22:18 +0000251 &total_video_delay_ms));
252 EXPECT_EQ(base_target_delay, total_video_delay_ms);
253 // The audio delay is not allowed to change more than the half of the
254 // required change in delay.
Yves Gerey665174f2018-06-19 15:03:05 +0200255 EXPECT_EQ(current_extra_delay_ms +
256 MaxAudioDelayIncrease(
257 current_audio_delay_ms,
258 base_target_delay + video_delay_ms - audio_delay_ms),
259 extra_audio_delay_ms);
mikhal@webrtc.orgef9f76a2013-02-15 23:22:18 +0000260 current_audio_delay_ms = extra_audio_delay_ms;
261 current_extra_delay_ms = extra_audio_delay_ms;
262
263 send_time_->IncreaseTimeMs(1000);
264 receive_time_->IncreaseTimeMs(800);
Yves Gerey665174f2018-06-19 15:03:05 +0200265 EXPECT_TRUE(DelayedStreams(audio_delay_ms, video_delay_ms,
266 current_audio_delay_ms, &extra_audio_delay_ms,
mikhal@webrtc.orgef9f76a2013-02-15 23:22:18 +0000267 &total_video_delay_ms));
268 EXPECT_EQ(base_target_delay, total_video_delay_ms);
269 // The audio delay is not allowed to change more than the half of the
270 // required change in delay.
Yves Gerey665174f2018-06-19 15:03:05 +0200271 EXPECT_EQ(current_extra_delay_ms +
272 MaxAudioDelayIncrease(
273 current_audio_delay_ms,
274 base_target_delay + video_delay_ms - audio_delay_ms),
275 extra_audio_delay_ms);
mikhal@webrtc.orgef9f76a2013-02-15 23:22:18 +0000276 current_extra_delay_ms = extra_audio_delay_ms;
277
278 // Simulate that NetEQ for some reason reduced the delay.
pwestin@webrtc.org63117332013-04-22 18:57:14 +0000279 current_audio_delay_ms = base_target_delay + 10;
mikhal@webrtc.orgef9f76a2013-02-15 23:22:18 +0000280 send_time_->IncreaseTimeMs(1000);
281 receive_time_->IncreaseTimeMs(800);
Yves Gerey665174f2018-06-19 15:03:05 +0200282 EXPECT_TRUE(DelayedStreams(audio_delay_ms, video_delay_ms,
283 current_audio_delay_ms, &extra_audio_delay_ms,
mikhal@webrtc.orgef9f76a2013-02-15 23:22:18 +0000284 &total_video_delay_ms));
285 EXPECT_EQ(base_target_delay, total_video_delay_ms);
286 // Since we only can ask NetEQ for a certain amount of extra delay, and
287 // we only measure the total NetEQ delay, we will ask for additional delay
288 // here to try to stay in sync.
Yves Gerey665174f2018-06-19 15:03:05 +0200289 EXPECT_EQ(current_extra_delay_ms +
290 MaxAudioDelayIncrease(
291 current_audio_delay_ms,
292 base_target_delay + video_delay_ms - audio_delay_ms),
293 extra_audio_delay_ms);
mikhal@webrtc.orgef9f76a2013-02-15 23:22:18 +0000294 current_extra_delay_ms = extra_audio_delay_ms;
295
296 // Simulate that NetEQ for some reason significantly increased the delay.
pwestin@webrtc.org63117332013-04-22 18:57:14 +0000297 current_audio_delay_ms = base_target_delay + 350;
mikhal@webrtc.orgef9f76a2013-02-15 23:22:18 +0000298 send_time_->IncreaseTimeMs(1000);
299 receive_time_->IncreaseTimeMs(800);
Yves Gerey665174f2018-06-19 15:03:05 +0200300 EXPECT_TRUE(DelayedStreams(audio_delay_ms, video_delay_ms,
301 current_audio_delay_ms, &extra_audio_delay_ms,
mikhal@webrtc.orgef9f76a2013-02-15 23:22:18 +0000302 &total_video_delay_ms));
303 EXPECT_EQ(base_target_delay, total_video_delay_ms);
304 // The audio delay is not allowed to change more than the half of the
305 // required change in delay.
Yves Gerey665174f2018-06-19 15:03:05 +0200306 EXPECT_EQ(current_extra_delay_ms +
307 MaxAudioDelayIncrease(
308 current_audio_delay_ms,
309 base_target_delay + video_delay_ms - audio_delay_ms),
310 extra_audio_delay_ms);
stefan@webrtc.org7c3523c2012-09-11 07:00:42 +0000311 }
312
stefan@webrtc.org5f284982012-06-28 07:51:16 +0000313 int MaxAudioDelayIncrease(int current_audio_delay_ms, int delay_ms) {
pwestin@webrtc.org63117332013-04-22 18:57:14 +0000314 return std::min((delay_ms - current_audio_delay_ms) / kSmoothingFilter,
Yves Gerey665174f2018-06-19 15:03:05 +0200315 static_cast<int>(kMaxAudioDiffMs));
stefan@webrtc.org5f284982012-06-28 07:51:16 +0000316 }
317
318 int MaxAudioDelayDecrease(int current_audio_delay_ms, int delay_ms) {
pwestin@webrtc.org63117332013-04-22 18:57:14 +0000319 return std::max((delay_ms - current_audio_delay_ms) / kSmoothingFilter,
320 -kMaxAudioDiffMs);
stefan@webrtc.org5f284982012-06-28 07:51:16 +0000321 }
322
stefan@webrtc.org7c3523c2012-09-11 07:00:42 +0000323 enum { kSendTimeOffsetMs = 98765 };
324 enum { kReceiveTimeOffsetMs = 43210 };
stefan@webrtc.org5f284982012-06-28 07:51:16 +0000325
326 StreamSynchronization* sync_;
Yves Gerey665174f2018-06-19 15:03:05 +0200327 Time* send_time_; // The simulated clock at the sender.
stefan@webrtc.org7c3523c2012-09-11 07:00:42 +0000328 Time* receive_time_; // The simulated clock at the receiver.
329 double audio_clock_drift_;
330 double video_clock_drift_;
stefan@webrtc.org5f284982012-06-28 07:51:16 +0000331};
332
333TEST_F(StreamSynchronizationTest, NoDelay) {
334 uint32_t current_audio_delay_ms = 0;
stefan@webrtc.org5f284982012-06-28 07:51:16 +0000335 int extra_audio_delay_ms = 0;
336 int total_video_delay_ms = 0;
337
pwestin@webrtc.org63117332013-04-22 18:57:14 +0000338 EXPECT_FALSE(DelayedStreams(0, 0, current_audio_delay_ms,
339 &extra_audio_delay_ms, &total_video_delay_ms));
stefan@webrtc.org5f284982012-06-28 07:51:16 +0000340 EXPECT_EQ(0, extra_audio_delay_ms);
341 EXPECT_EQ(0, total_video_delay_ms);
342}
343
344TEST_F(StreamSynchronizationTest, VideoDelay) {
345 uint32_t current_audio_delay_ms = 0;
346 int delay_ms = 200;
347 int extra_audio_delay_ms = 0;
348 int total_video_delay_ms = 0;
349
stefan@webrtc.org7c3523c2012-09-11 07:00:42 +0000350 EXPECT_TRUE(DelayedStreams(delay_ms, 0, current_audio_delay_ms,
351 &extra_audio_delay_ms, &total_video_delay_ms));
stefan@webrtc.org5f284982012-06-28 07:51:16 +0000352 EXPECT_EQ(0, extra_audio_delay_ms);
353 // The video delay is not allowed to change more than this in 1 second.
pwestin@webrtc.org63117332013-04-22 18:57:14 +0000354 EXPECT_EQ(delay_ms / kSmoothingFilter, total_video_delay_ms);
stefan@webrtc.org5f284982012-06-28 07:51:16 +0000355
356 send_time_->IncreaseTimeMs(1000);
357 receive_time_->IncreaseTimeMs(800);
358 // Simulate 0 minimum delay in the VCM.
359 total_video_delay_ms = 0;
stefan@webrtc.org7c3523c2012-09-11 07:00:42 +0000360 EXPECT_TRUE(DelayedStreams(delay_ms, 0, current_audio_delay_ms,
361 &extra_audio_delay_ms, &total_video_delay_ms));
stefan@webrtc.org5f284982012-06-28 07:51:16 +0000362 EXPECT_EQ(0, extra_audio_delay_ms);
363 // The video delay is not allowed to change more than this in 1 second.
pwestin@webrtc.org63117332013-04-22 18:57:14 +0000364 EXPECT_EQ(2 * delay_ms / kSmoothingFilter, total_video_delay_ms);
stefan@webrtc.org5f284982012-06-28 07:51:16 +0000365
366 send_time_->IncreaseTimeMs(1000);
367 receive_time_->IncreaseTimeMs(800);
368 // Simulate 0 minimum delay in the VCM.
369 total_video_delay_ms = 0;
stefan@webrtc.org7c3523c2012-09-11 07:00:42 +0000370 EXPECT_TRUE(DelayedStreams(delay_ms, 0, current_audio_delay_ms,
371 &extra_audio_delay_ms, &total_video_delay_ms));
stefan@webrtc.org5f284982012-06-28 07:51:16 +0000372 EXPECT_EQ(0, extra_audio_delay_ms);
pwestin@webrtc.org63117332013-04-22 18:57:14 +0000373 EXPECT_EQ(3 * delay_ms / kSmoothingFilter, total_video_delay_ms);
stefan@webrtc.org5f284982012-06-28 07:51:16 +0000374}
375
376TEST_F(StreamSynchronizationTest, AudioDelay) {
377 int current_audio_delay_ms = 0;
378 int delay_ms = 200;
379 int extra_audio_delay_ms = 0;
stefan@webrtc.org5f284982012-06-28 07:51:16 +0000380 int total_video_delay_ms = 0;
381
stefan@webrtc.org7c3523c2012-09-11 07:00:42 +0000382 EXPECT_TRUE(DelayedStreams(0, delay_ms, current_audio_delay_ms,
383 &extra_audio_delay_ms, &total_video_delay_ms));
stefan@webrtc.org5f284982012-06-28 07:51:16 +0000384 EXPECT_EQ(0, total_video_delay_ms);
385 // The audio delay is not allowed to change more than this in 1 second.
pwestin@webrtc.org63117332013-04-22 18:57:14 +0000386 EXPECT_EQ(delay_ms / kSmoothingFilter, extra_audio_delay_ms);
stefan@webrtc.org5f284982012-06-28 07:51:16 +0000387 current_audio_delay_ms = extra_audio_delay_ms;
andrew@webrtc.orgd7a71d02012-08-01 01:40:02 +0000388 int current_extra_delay_ms = extra_audio_delay_ms;
stefan@webrtc.org5f284982012-06-28 07:51:16 +0000389
390 send_time_->IncreaseTimeMs(1000);
391 receive_time_->IncreaseTimeMs(800);
stefan@webrtc.org7c3523c2012-09-11 07:00:42 +0000392 EXPECT_TRUE(DelayedStreams(0, delay_ms, current_audio_delay_ms,
393 &extra_audio_delay_ms, &total_video_delay_ms));
stefan@webrtc.org5f284982012-06-28 07:51:16 +0000394 EXPECT_EQ(0, total_video_delay_ms);
395 // The audio delay is not allowed to change more than the half of the required
396 // change in delay.
397 EXPECT_EQ(current_extra_delay_ms +
Yves Gerey665174f2018-06-19 15:03:05 +0200398 MaxAudioDelayIncrease(current_audio_delay_ms, delay_ms),
stefan@webrtc.org5f284982012-06-28 07:51:16 +0000399 extra_audio_delay_ms);
400 current_audio_delay_ms = extra_audio_delay_ms;
401 current_extra_delay_ms = extra_audio_delay_ms;
402
403 send_time_->IncreaseTimeMs(1000);
404 receive_time_->IncreaseTimeMs(800);
stefan@webrtc.org7c3523c2012-09-11 07:00:42 +0000405 EXPECT_TRUE(DelayedStreams(0, delay_ms, current_audio_delay_ms,
406 &extra_audio_delay_ms, &total_video_delay_ms));
stefan@webrtc.org5f284982012-06-28 07:51:16 +0000407 EXPECT_EQ(0, total_video_delay_ms);
408 // The audio delay is not allowed to change more than the half of the required
409 // change in delay.
410 EXPECT_EQ(current_extra_delay_ms +
Yves Gerey665174f2018-06-19 15:03:05 +0200411 MaxAudioDelayIncrease(current_audio_delay_ms, delay_ms),
stefan@webrtc.org5f284982012-06-28 07:51:16 +0000412 extra_audio_delay_ms);
413 current_extra_delay_ms = extra_audio_delay_ms;
414
415 // Simulate that NetEQ for some reason reduced the delay.
pwestin@webrtc.org63117332013-04-22 18:57:14 +0000416 current_audio_delay_ms = 10;
stefan@webrtc.org5f284982012-06-28 07:51:16 +0000417 send_time_->IncreaseTimeMs(1000);
418 receive_time_->IncreaseTimeMs(800);
stefan@webrtc.org7c3523c2012-09-11 07:00:42 +0000419 EXPECT_TRUE(DelayedStreams(0, delay_ms, current_audio_delay_ms,
420 &extra_audio_delay_ms, &total_video_delay_ms));
stefan@webrtc.org5f284982012-06-28 07:51:16 +0000421 EXPECT_EQ(0, total_video_delay_ms);
422 // Since we only can ask NetEQ for a certain amount of extra delay, and
423 // we only measure the total NetEQ delay, we will ask for additional delay
424 // here to try to
425 EXPECT_EQ(current_extra_delay_ms +
Yves Gerey665174f2018-06-19 15:03:05 +0200426 MaxAudioDelayIncrease(current_audio_delay_ms, delay_ms),
stefan@webrtc.org5f284982012-06-28 07:51:16 +0000427 extra_audio_delay_ms);
428 current_extra_delay_ms = extra_audio_delay_ms;
429
430 // Simulate that NetEQ for some reason significantly increased the delay.
pwestin@webrtc.org63117332013-04-22 18:57:14 +0000431 current_audio_delay_ms = 350;
stefan@webrtc.org5f284982012-06-28 07:51:16 +0000432 send_time_->IncreaseTimeMs(1000);
433 receive_time_->IncreaseTimeMs(800);
stefan@webrtc.org7c3523c2012-09-11 07:00:42 +0000434 EXPECT_TRUE(DelayedStreams(0, delay_ms, current_audio_delay_ms,
435 &extra_audio_delay_ms, &total_video_delay_ms));
stefan@webrtc.org5f284982012-06-28 07:51:16 +0000436 EXPECT_EQ(0, total_video_delay_ms);
437 // The audio delay is not allowed to change more than the half of the required
438 // change in delay.
439 EXPECT_EQ(current_extra_delay_ms +
Yves Gerey665174f2018-06-19 15:03:05 +0200440 MaxAudioDelayDecrease(current_audio_delay_ms, delay_ms),
stefan@webrtc.org5f284982012-06-28 07:51:16 +0000441 extra_audio_delay_ms);
442}
443
444TEST_F(StreamSynchronizationTest, BothDelayedVideoLater) {
mikhal@webrtc.orgef9f76a2013-02-15 23:22:18 +0000445 BothDelayedVideoLaterTest(0);
446}
stefan@webrtc.org5f284982012-06-28 07:51:16 +0000447
mikhal@webrtc.orgef9f76a2013-02-15 23:22:18 +0000448TEST_F(StreamSynchronizationTest, BothDelayedVideoLaterAudioClockDrift) {
449 audio_clock_drift_ = 1.05;
450 BothDelayedVideoLaterTest(0);
451}
stefan@webrtc.org5f284982012-06-28 07:51:16 +0000452
mikhal@webrtc.orgef9f76a2013-02-15 23:22:18 +0000453TEST_F(StreamSynchronizationTest, BothDelayedVideoLaterVideoClockDrift) {
454 video_clock_drift_ = 1.05;
455 BothDelayedVideoLaterTest(0);
stefan@webrtc.org5f284982012-06-28 07:51:16 +0000456}
457
458TEST_F(StreamSynchronizationTest, BothDelayedAudioLater) {
mikhal@webrtc.orgef9f76a2013-02-15 23:22:18 +0000459 BothDelayedAudioLaterTest(0);
stefan@webrtc.org7c3523c2012-09-11 07:00:42 +0000460}
stefan@webrtc.org5f284982012-06-28 07:51:16 +0000461
stefan@webrtc.org7c3523c2012-09-11 07:00:42 +0000462TEST_F(StreamSynchronizationTest, BothDelayedAudioClockDrift) {
463 audio_clock_drift_ = 1.05;
mikhal@webrtc.orgef9f76a2013-02-15 23:22:18 +0000464 BothDelayedAudioLaterTest(0);
stefan@webrtc.org7c3523c2012-09-11 07:00:42 +0000465}
stefan@webrtc.org5f284982012-06-28 07:51:16 +0000466
stefan@webrtc.org7c3523c2012-09-11 07:00:42 +0000467TEST_F(StreamSynchronizationTest, BothDelayedVideoClockDrift) {
468 video_clock_drift_ = 1.05;
mikhal@webrtc.orgef9f76a2013-02-15 23:22:18 +0000469 BothDelayedAudioLaterTest(0);
stefan@webrtc.org7c3523c2012-09-11 07:00:42 +0000470}
mikhal@webrtc.orgef9f76a2013-02-15 23:22:18 +0000471
472TEST_F(StreamSynchronizationTest, BaseDelay) {
473 int base_target_delay_ms = 2000;
474 int current_audio_delay_ms = 2000;
475 int extra_audio_delay_ms = 0;
476 int total_video_delay_ms = base_target_delay_ms;
477 sync_->SetTargetBufferingDelay(base_target_delay_ms);
pwestin@webrtc.org63117332013-04-22 18:57:14 +0000478 // We are in sync don't change.
479 EXPECT_FALSE(DelayedStreams(base_target_delay_ms, base_target_delay_ms,
Yves Gerey665174f2018-06-19 15:03:05 +0200480 current_audio_delay_ms, &extra_audio_delay_ms,
481 &total_video_delay_ms));
mikhal@webrtc.org0d8d0102013-02-22 19:30:44 +0000482 // Triggering another call with the same values. Delay should not be modified.
483 base_target_delay_ms = 2000;
484 current_audio_delay_ms = base_target_delay_ms;
485 total_video_delay_ms = base_target_delay_ms;
486 sync_->SetTargetBufferingDelay(base_target_delay_ms);
pwestin@webrtc.org63117332013-04-22 18:57:14 +0000487 // We are in sync don't change.
488 EXPECT_FALSE(DelayedStreams(base_target_delay_ms, base_target_delay_ms,
Yves Gerey665174f2018-06-19 15:03:05 +0200489 current_audio_delay_ms, &extra_audio_delay_ms,
490 &total_video_delay_ms));
mikhal@webrtc.org0d8d0102013-02-22 19:30:44 +0000491 // Changing delay value - intended to test this module only. In practice it
492 // would take VoE time to adapt.
493 base_target_delay_ms = 5000;
494 current_audio_delay_ms = base_target_delay_ms;
495 total_video_delay_ms = base_target_delay_ms;
496 sync_->SetTargetBufferingDelay(base_target_delay_ms);
pwestin@webrtc.org63117332013-04-22 18:57:14 +0000497 // We are in sync don't change.
498 EXPECT_FALSE(DelayedStreams(base_target_delay_ms, base_target_delay_ms,
Yves Gerey665174f2018-06-19 15:03:05 +0200499 current_audio_delay_ms, &extra_audio_delay_ms,
500 &total_video_delay_ms));
mikhal@webrtc.orgef9f76a2013-02-15 23:22:18 +0000501}
502
503TEST_F(StreamSynchronizationTest, BothDelayedAudioLaterWithBaseDelay) {
504 int base_target_delay_ms = 3000;
505 sync_->SetTargetBufferingDelay(base_target_delay_ms);
506 BothDelayedAudioLaterTest(base_target_delay_ms);
507}
508
509TEST_F(StreamSynchronizationTest, BothDelayedAudioClockDriftWithBaseDelay) {
510 int base_target_delay_ms = 3000;
511 sync_->SetTargetBufferingDelay(base_target_delay_ms);
512 audio_clock_drift_ = 1.05;
513 BothDelayedAudioLaterTest(base_target_delay_ms);
514}
515
516TEST_F(StreamSynchronizationTest, BothDelayedVideoClockDriftWithBaseDelay) {
517 int base_target_delay_ms = 3000;
518 sync_->SetTargetBufferingDelay(base_target_delay_ms);
519 video_clock_drift_ = 1.05;
520 BothDelayedAudioLaterTest(base_target_delay_ms);
521}
522
523TEST_F(StreamSynchronizationTest, BothDelayedVideoLaterWithBaseDelay) {
524 int base_target_delay_ms = 2000;
525 sync_->SetTargetBufferingDelay(base_target_delay_ms);
526 BothDelayedVideoLaterTest(base_target_delay_ms);
527}
528
529TEST_F(StreamSynchronizationTest,
530 BothDelayedVideoLaterAudioClockDriftWithBaseDelay) {
531 int base_target_delay_ms = 2000;
532 audio_clock_drift_ = 1.05;
533 sync_->SetTargetBufferingDelay(base_target_delay_ms);
534 BothDelayedVideoLaterTest(base_target_delay_ms);
535}
536
537TEST_F(StreamSynchronizationTest,
538 BothDelayedVideoLaterVideoClockDriftWithBaseDelay) {
539 int base_target_delay_ms = 2000;
540 video_clock_drift_ = 1.05;
541 sync_->SetTargetBufferingDelay(base_target_delay_ms);
542 BothDelayedVideoLaterTest(base_target_delay_ms);
543}
544
stefan@webrtc.org5f284982012-06-28 07:51:16 +0000545} // namespace webrtc