1 /*
2 * Copyright (c) 2011 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
11 #include "modules/video_coding/timing/timing.h"
12
13 #include "api/units/frequency.h"
14 #include "api/units/time_delta.h"
15 #include "system_wrappers/include/clock.h"
16 #include "test/gtest.h"
17 #include "test/scoped_key_value_config.h"
18
19 namespace webrtc {
20 namespace {
21
22 constexpr Frequency k25Fps = Frequency::Hertz(25);
23 constexpr Frequency k90kHz = Frequency::KiloHertz(90);
24
25 } // namespace
26
TEST(ReceiverTimingTest,JitterDelay)27 TEST(ReceiverTimingTest, JitterDelay) {
28 test::ScopedKeyValueConfig field_trials;
29 SimulatedClock clock(0);
30 VCMTiming timing(&clock, field_trials);
31 timing.Reset();
32
33 uint32_t timestamp = 0;
34 timing.UpdateCurrentDelay(timestamp);
35
36 timing.Reset();
37
38 timing.IncomingTimestamp(timestamp, clock.CurrentTime());
39 TimeDelta jitter_delay = TimeDelta::Millis(20);
40 timing.SetJitterDelay(jitter_delay);
41 timing.UpdateCurrentDelay(timestamp);
42 timing.set_render_delay(TimeDelta::Zero());
43 auto wait_time = timing.MaxWaitingTime(
44 timing.RenderTime(timestamp, clock.CurrentTime()), clock.CurrentTime(),
45 /*too_many_frames_queued=*/false);
46 // First update initializes the render time. Since we have no decode delay
47 // we get wait_time = renderTime - now - renderDelay = jitter.
48 EXPECT_EQ(jitter_delay, wait_time);
49
50 jitter_delay += TimeDelta::Millis(VCMTiming::kDelayMaxChangeMsPerS + 10);
51 timestamp += 90000;
52 clock.AdvanceTimeMilliseconds(1000);
53 timing.SetJitterDelay(jitter_delay);
54 timing.UpdateCurrentDelay(timestamp);
55 wait_time = timing.MaxWaitingTime(
56 timing.RenderTime(timestamp, clock.CurrentTime()), clock.CurrentTime(),
57 /*too_many_frames_queued=*/false);
58 // Since we gradually increase the delay we only get 100 ms every second.
59 EXPECT_EQ(jitter_delay - TimeDelta::Millis(10), wait_time);
60
61 timestamp += 90000;
62 clock.AdvanceTimeMilliseconds(1000);
63 timing.UpdateCurrentDelay(timestamp);
64 wait_time = timing.MaxWaitingTime(
65 timing.RenderTime(timestamp, clock.CurrentTime()), clock.CurrentTime(),
66 /*too_many_frames_queued=*/false);
67 EXPECT_EQ(jitter_delay, wait_time);
68
69 // Insert frames without jitter, verify that this gives the exact wait time.
70 const int kNumFrames = 300;
71 for (int i = 0; i < kNumFrames; i++) {
72 clock.AdvanceTime(1 / k25Fps);
73 timestamp += k90kHz / k25Fps;
74 timing.IncomingTimestamp(timestamp, clock.CurrentTime());
75 }
76 timing.UpdateCurrentDelay(timestamp);
77 wait_time = timing.MaxWaitingTime(
78 timing.RenderTime(timestamp, clock.CurrentTime()), clock.CurrentTime(),
79 /*too_many_frames_queued=*/false);
80 EXPECT_EQ(jitter_delay, wait_time);
81
82 // Add decode time estimates for 1 second.
83 const TimeDelta kDecodeTime = TimeDelta::Millis(10);
84 for (int i = 0; i < k25Fps.hertz(); i++) {
85 clock.AdvanceTime(kDecodeTime);
86 timing.StopDecodeTimer(kDecodeTime, clock.CurrentTime());
87 timestamp += k90kHz / k25Fps;
88 clock.AdvanceTime(1 / k25Fps - kDecodeTime);
89 timing.IncomingTimestamp(timestamp, clock.CurrentTime());
90 }
91 timing.UpdateCurrentDelay(timestamp);
92 wait_time = timing.MaxWaitingTime(
93 timing.RenderTime(timestamp, clock.CurrentTime()), clock.CurrentTime(),
94 /*too_many_frames_queued=*/false);
95 EXPECT_EQ(jitter_delay, wait_time);
96
97 const TimeDelta kMinTotalDelay = TimeDelta::Millis(200);
98 timing.set_min_playout_delay(kMinTotalDelay);
99 clock.AdvanceTimeMilliseconds(5000);
100 timestamp += 5 * 90000;
101 timing.UpdateCurrentDelay(timestamp);
102 const TimeDelta kRenderDelay = TimeDelta::Millis(10);
103 timing.set_render_delay(kRenderDelay);
104 wait_time = timing.MaxWaitingTime(
105 timing.RenderTime(timestamp, clock.CurrentTime()), clock.CurrentTime(),
106 /*too_many_frames_queued=*/false);
107 // We should at least have kMinTotalDelayMs - decodeTime (10) - renderTime
108 // (10) to wait.
109 EXPECT_EQ(kMinTotalDelay - kDecodeTime - kRenderDelay, wait_time);
110 // The total video delay should be equal to the min total delay.
111 EXPECT_EQ(kMinTotalDelay, timing.TargetVideoDelay());
112
113 // Reset playout delay.
114 timing.set_min_playout_delay(TimeDelta::Zero());
115 clock.AdvanceTimeMilliseconds(5000);
116 timestamp += 5 * 90000;
117 timing.UpdateCurrentDelay(timestamp);
118 }
119
TEST(ReceiverTimingTest,TimestampWrapAround)120 TEST(ReceiverTimingTest, TimestampWrapAround) {
121 constexpr auto kStartTime = Timestamp::Millis(1337);
122 test::ScopedKeyValueConfig field_trials;
123 SimulatedClock clock(kStartTime);
124 VCMTiming timing(&clock, field_trials);
125
126 // Provoke a wrap-around. The fifth frame will have wrapped at 25 fps.
127 constexpr uint32_t kRtpTicksPerFrame = k90kHz / k25Fps;
128 uint32_t timestamp = 0xFFFFFFFFu - 3 * kRtpTicksPerFrame;
129 for (int i = 0; i < 5; ++i) {
130 timing.IncomingTimestamp(timestamp, clock.CurrentTime());
131 clock.AdvanceTime(1 / k25Fps);
132 timestamp += kRtpTicksPerFrame;
133 EXPECT_EQ(kStartTime + 3 / k25Fps,
134 timing.RenderTime(0xFFFFFFFFu, clock.CurrentTime()));
135 // One ms later in 90 kHz.
136 EXPECT_EQ(kStartTime + 3 / k25Fps + TimeDelta::Millis(1),
137 timing.RenderTime(89u, clock.CurrentTime()));
138 }
139 }
140
TEST(ReceiverTimingTest,UseLowLatencyRenderer)141 TEST(ReceiverTimingTest, UseLowLatencyRenderer) {
142 test::ScopedKeyValueConfig field_trials;
143 SimulatedClock clock(0);
144 VCMTiming timing(&clock, field_trials);
145 timing.Reset();
146 // Default is false.
147 EXPECT_FALSE(timing.RenderParameters().use_low_latency_rendering);
148 // False if min playout delay > 0.
149 timing.set_min_playout_delay(TimeDelta::Millis(10));
150 timing.set_max_playout_delay(TimeDelta::Millis(20));
151 EXPECT_FALSE(timing.RenderParameters().use_low_latency_rendering);
152 // True if min==0, max > 0.
153 timing.set_min_playout_delay(TimeDelta::Zero());
154 EXPECT_TRUE(timing.RenderParameters().use_low_latency_rendering);
155 // True if min==max==0.
156 timing.set_max_playout_delay(TimeDelta::Zero());
157 EXPECT_TRUE(timing.RenderParameters().use_low_latency_rendering);
158 // True also for max playout delay==500 ms.
159 timing.set_max_playout_delay(TimeDelta::Millis(500));
160 EXPECT_TRUE(timing.RenderParameters().use_low_latency_rendering);
161 // False if max playout delay > 500 ms.
162 timing.set_max_playout_delay(TimeDelta::Millis(501));
163 EXPECT_FALSE(timing.RenderParameters().use_low_latency_rendering);
164 }
165
TEST(ReceiverTimingTest,MaxWaitingTimeIsZeroForZeroRenderTime)166 TEST(ReceiverTimingTest, MaxWaitingTimeIsZeroForZeroRenderTime) {
167 // This is the default path when the RTP playout delay header extension is set
168 // to min==0 and max==0.
169 constexpr int64_t kStartTimeUs = 3.15e13; // About one year in us.
170 constexpr TimeDelta kTimeDelta = 1 / Frequency::Hertz(60);
171 constexpr Timestamp kZeroRenderTime = Timestamp::Zero();
172 SimulatedClock clock(kStartTimeUs);
173 test::ScopedKeyValueConfig field_trials;
174 VCMTiming timing(&clock, field_trials);
175 timing.Reset();
176 timing.set_max_playout_delay(TimeDelta::Zero());
177 for (int i = 0; i < 10; ++i) {
178 clock.AdvanceTime(kTimeDelta);
179 Timestamp now = clock.CurrentTime();
180 EXPECT_LT(timing.MaxWaitingTime(kZeroRenderTime, now,
181 /*too_many_frames_queued=*/false),
182 TimeDelta::Zero());
183 }
184 // Another frame submitted at the same time also returns a negative max
185 // waiting time.
186 Timestamp now = clock.CurrentTime();
187 EXPECT_LT(timing.MaxWaitingTime(kZeroRenderTime, now,
188 /*too_many_frames_queued=*/false),
189 TimeDelta::Zero());
190 // MaxWaitingTime should be less than zero even if there's a burst of frames.
191 EXPECT_LT(timing.MaxWaitingTime(kZeroRenderTime, now,
192 /*too_many_frames_queued=*/false),
193 TimeDelta::Zero());
194 EXPECT_LT(timing.MaxWaitingTime(kZeroRenderTime, now,
195 /*too_many_frames_queued=*/false),
196 TimeDelta::Zero());
197 EXPECT_LT(timing.MaxWaitingTime(kZeroRenderTime, now,
198 /*too_many_frames_queued=*/false),
199 TimeDelta::Zero());
200 }
201
TEST(ReceiverTimingTest,MaxWaitingTimeZeroDelayPacingExperiment)202 TEST(ReceiverTimingTest, MaxWaitingTimeZeroDelayPacingExperiment) {
203 // The minimum pacing is enabled by a field trial and active if the RTP
204 // playout delay header extension is set to min==0.
205 constexpr TimeDelta kMinPacing = TimeDelta::Millis(3);
206 test::ScopedKeyValueConfig field_trials(
207 "WebRTC-ZeroPlayoutDelay/min_pacing:3ms/");
208 constexpr int64_t kStartTimeUs = 3.15e13; // About one year in us.
209 constexpr TimeDelta kTimeDelta = 1 / Frequency::Hertz(60);
210 constexpr auto kZeroRenderTime = Timestamp::Zero();
211 SimulatedClock clock(kStartTimeUs);
212 VCMTiming timing(&clock, field_trials);
213 timing.Reset();
214 // MaxWaitingTime() returns zero for evenly spaced video frames.
215 for (int i = 0; i < 10; ++i) {
216 clock.AdvanceTime(kTimeDelta);
217 Timestamp now = clock.CurrentTime();
218 EXPECT_EQ(timing.MaxWaitingTime(kZeroRenderTime, now,
219 /*too_many_frames_queued=*/false),
220 TimeDelta::Zero());
221 timing.SetLastDecodeScheduledTimestamp(now);
222 }
223 // Another frame submitted at the same time is paced according to the field
224 // trial setting.
225 auto now = clock.CurrentTime();
226 EXPECT_EQ(timing.MaxWaitingTime(kZeroRenderTime, now,
227 /*too_many_frames_queued=*/false),
228 kMinPacing);
229 // If there's a burst of frames, the wait time is calculated based on next
230 // decode time.
231 EXPECT_EQ(timing.MaxWaitingTime(kZeroRenderTime, now,
232 /*too_many_frames_queued=*/false),
233 kMinPacing);
234 EXPECT_EQ(timing.MaxWaitingTime(kZeroRenderTime, now,
235 /*too_many_frames_queued=*/false),
236 kMinPacing);
237 // Allow a few ms to pass, this should be subtracted from the MaxWaitingTime.
238 constexpr TimeDelta kTwoMs = TimeDelta::Millis(2);
239 clock.AdvanceTime(kTwoMs);
240 now = clock.CurrentTime();
241 EXPECT_EQ(timing.MaxWaitingTime(kZeroRenderTime, now,
242 /*too_many_frames_queued=*/false),
243 kMinPacing - kTwoMs);
244 // A frame is decoded at the current time, the wait time should be restored to
245 // pacing delay.
246 timing.SetLastDecodeScheduledTimestamp(now);
247 EXPECT_EQ(timing.MaxWaitingTime(kZeroRenderTime, now,
248 /*too_many_frames_queued=*/false),
249 kMinPacing);
250 }
251
TEST(ReceiverTimingTest,DefaultMaxWaitingTimeUnaffectedByPacingExperiment)252 TEST(ReceiverTimingTest, DefaultMaxWaitingTimeUnaffectedByPacingExperiment) {
253 // The minimum pacing is enabled by a field trial but should not have any
254 // effect if render_time_ms is greater than 0;
255 test::ScopedKeyValueConfig field_trials(
256 "WebRTC-ZeroPlayoutDelay/min_pacing:3ms/");
257 constexpr int64_t kStartTimeUs = 3.15e13; // About one year in us.
258 const TimeDelta kTimeDelta = TimeDelta::Millis(1000.0 / 60.0);
259 SimulatedClock clock(kStartTimeUs);
260 VCMTiming timing(&clock, field_trials);
261 timing.Reset();
262 clock.AdvanceTime(kTimeDelta);
263 auto now = clock.CurrentTime();
264 Timestamp render_time = now + TimeDelta::Millis(30);
265 // Estimate the internal processing delay from the first frame.
266 TimeDelta estimated_processing_delay =
267 (render_time - now) -
268 timing.MaxWaitingTime(render_time, now,
269 /*too_many_frames_queued=*/false);
270 EXPECT_GT(estimated_processing_delay, TimeDelta::Zero());
271
272 // Any other frame submitted at the same time should be scheduled according to
273 // its render time.
274 for (int i = 0; i < 5; ++i) {
275 render_time += kTimeDelta;
276 EXPECT_EQ(timing.MaxWaitingTime(render_time, now,
277 /*too_many_frames_queued=*/false),
278 render_time - now - estimated_processing_delay);
279 }
280 }
281
TEST(ReceiverTimingTest,MaxWaitingTimeReturnsZeroIfTooManyFramesQueuedIsTrue)282 TEST(ReceiverTimingTest, MaxWaitingTimeReturnsZeroIfTooManyFramesQueuedIsTrue) {
283 // The minimum pacing is enabled by a field trial and active if the RTP
284 // playout delay header extension is set to min==0.
285 constexpr TimeDelta kMinPacing = TimeDelta::Millis(3);
286 test::ScopedKeyValueConfig field_trials(
287 "WebRTC-ZeroPlayoutDelay/min_pacing:3ms/");
288 constexpr int64_t kStartTimeUs = 3.15e13; // About one year in us.
289 const TimeDelta kTimeDelta = TimeDelta::Millis(1000.0 / 60.0);
290 constexpr auto kZeroRenderTime = Timestamp::Zero();
291 SimulatedClock clock(kStartTimeUs);
292 VCMTiming timing(&clock, field_trials);
293 timing.Reset();
294 // MaxWaitingTime() returns zero for evenly spaced video frames.
295 for (int i = 0; i < 10; ++i) {
296 clock.AdvanceTime(kTimeDelta);
297 auto now = clock.CurrentTime();
298 EXPECT_EQ(timing.MaxWaitingTime(kZeroRenderTime, now,
299 /*too_many_frames_queued=*/false),
300 TimeDelta::Zero());
301 timing.SetLastDecodeScheduledTimestamp(now);
302 }
303 // Another frame submitted at the same time is paced according to the field
304 // trial setting.
305 auto now_ms = clock.CurrentTime();
306 EXPECT_EQ(timing.MaxWaitingTime(kZeroRenderTime, now_ms,
307 /*too_many_frames_queued=*/false),
308 kMinPacing);
309 // MaxWaitingTime returns 0 even if there's a burst of frames if
310 // too_many_frames_queued is set to true.
311 EXPECT_EQ(timing.MaxWaitingTime(kZeroRenderTime, now_ms,
312 /*too_many_frames_queued=*/true),
313 TimeDelta::Zero());
314 EXPECT_EQ(timing.MaxWaitingTime(kZeroRenderTime, now_ms,
315 /*too_many_frames_queued=*/true),
316 TimeDelta::Zero());
317 }
318
TEST(ReceiverTimingTest,UpdateCurrentDelayCapsWhenOffByMicroseconds)319 TEST(ReceiverTimingTest, UpdateCurrentDelayCapsWhenOffByMicroseconds) {
320 test::ScopedKeyValueConfig field_trials;
321 SimulatedClock clock(0);
322 VCMTiming timing(&clock, field_trials);
323 timing.Reset();
324
325 // Set larger initial current delay.
326 timing.set_min_playout_delay(TimeDelta::Millis(200));
327 timing.UpdateCurrentDelay(Timestamp::Millis(900), Timestamp::Millis(1000));
328
329 // Add a few microseconds to ensure that the delta of decode time is 0 after
330 // rounding, and should reset to the target delay.
331 timing.set_min_playout_delay(TimeDelta::Millis(50));
332 Timestamp decode_time = Timestamp::Millis(1337);
333 Timestamp render_time =
334 decode_time + TimeDelta::Millis(10) + TimeDelta::Micros(37);
335 timing.UpdateCurrentDelay(render_time, decode_time);
336 EXPECT_EQ(timing.GetTimings().current_delay, timing.TargetVideoDelay());
337 }
338
339 } // namespace webrtc
340