xref: /aosp_15_r20/external/webrtc/modules/video_coding/timing/inter_frame_delay_unittest.cc (revision d9f758449e529ab9291ac668be2861e7a55c2422)
1 /*
2  *  Copyright (c) 2022 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/inter_frame_delay.h"
12 
13 #include <limits>
14 
15 #include "absl/types/optional.h"
16 #include "api/units/frequency.h"
17 #include "api/units/time_delta.h"
18 #include "api/units/timestamp.h"
19 #include "system_wrappers/include/clock.h"
20 #include "test/gmock.h"
21 #include "test/gtest.h"
22 
23 namespace webrtc {
24 
25 namespace {
26 
27 // Test is for frames at 30fps. At 30fps, RTP timestamps will increase by
28 // 90000 / 30 = 3000 ticks per frame.
29 constexpr Frequency k30Fps = Frequency::Hertz(30);
30 constexpr TimeDelta kFrameDelay = 1 / k30Fps;
31 constexpr uint32_t kRtpTicksPerFrame = Frequency::KiloHertz(90) / k30Fps;
32 constexpr Timestamp kStartTime = Timestamp::Millis(1337);
33 
34 }  // namespace
35 
36 using ::testing::Eq;
37 using ::testing::Optional;
38 
TEST(InterFrameDelayTest,OldRtpTimestamp)39 TEST(InterFrameDelayTest, OldRtpTimestamp) {
40   InterFrameDelay inter_frame_delay;
41   EXPECT_THAT(inter_frame_delay.CalculateDelay(180000, kStartTime),
42               Optional(TimeDelta::Zero()));
43   EXPECT_THAT(inter_frame_delay.CalculateDelay(90000, kStartTime),
44               Eq(absl::nullopt));
45 }
46 
TEST(InterFrameDelayTest,NegativeWrapAroundIsSameAsOldRtpTimestamp)47 TEST(InterFrameDelayTest, NegativeWrapAroundIsSameAsOldRtpTimestamp) {
48   InterFrameDelay inter_frame_delay;
49   uint32_t rtp = 1500;
50   EXPECT_THAT(inter_frame_delay.CalculateDelay(rtp, kStartTime),
51               Optional(TimeDelta::Zero()));
52   // RTP has wrapped around backwards.
53   rtp -= 3000;
54   EXPECT_THAT(inter_frame_delay.CalculateDelay(rtp, kStartTime),
55               Eq(absl::nullopt));
56 }
57 
TEST(InterFrameDelayTest,CorrectDelayForFrames)58 TEST(InterFrameDelayTest, CorrectDelayForFrames) {
59   InterFrameDelay inter_frame_delay;
60   // Use a fake clock to simplify time keeping.
61   SimulatedClock clock(kStartTime);
62 
63   // First frame is always delay 0.
64   uint32_t rtp = 90000;
65   EXPECT_THAT(inter_frame_delay.CalculateDelay(rtp, clock.CurrentTime()),
66               Optional(TimeDelta::Zero()));
67 
68   // Perfectly timed frame has 0 delay.
69   clock.AdvanceTime(kFrameDelay);
70   rtp += kRtpTicksPerFrame;
71   EXPECT_THAT(inter_frame_delay.CalculateDelay(rtp, clock.CurrentTime()),
72               Optional(TimeDelta::Zero()));
73 
74   // Slightly early frame will have a negative delay.
75   clock.AdvanceTime(kFrameDelay - TimeDelta::Millis(3));
76   rtp += kRtpTicksPerFrame;
77   EXPECT_THAT(inter_frame_delay.CalculateDelay(rtp, clock.CurrentTime()),
78               Optional(-TimeDelta::Millis(3)));
79 
80   // Slightly late frame will have positive delay.
81   clock.AdvanceTime(kFrameDelay + TimeDelta::Micros(5125));
82   rtp += kRtpTicksPerFrame;
83   EXPECT_THAT(inter_frame_delay.CalculateDelay(rtp, clock.CurrentTime()),
84               Optional(TimeDelta::Micros(5125)));
85 
86   // Simulate faster frame RTP at the same clock delay. The frame arrives late,
87   // since the RTP timestamp is faster than the delay, and thus is positive.
88   clock.AdvanceTime(kFrameDelay);
89   rtp += kRtpTicksPerFrame / 2;
90   EXPECT_THAT(inter_frame_delay.CalculateDelay(rtp, clock.CurrentTime()),
91               Optional(kFrameDelay / 2.0));
92 
93   // Simulate slower frame RTP at the same clock delay. The frame is early,
94   // since the RTP timestamp advanced more than the delay, and thus is negative.
95   clock.AdvanceTime(kFrameDelay);
96   rtp += 1.5 * kRtpTicksPerFrame;
97   EXPECT_THAT(inter_frame_delay.CalculateDelay(rtp, clock.CurrentTime()),
98               Optional(-kFrameDelay / 2.0));
99 }
100 
TEST(InterFrameDelayTest,PositiveWrapAround)101 TEST(InterFrameDelayTest, PositiveWrapAround) {
102   InterFrameDelay inter_frame_delay;
103   // Use a fake clock to simplify time keeping.
104   SimulatedClock clock(kStartTime);
105 
106   // First frame is behind the max RTP by 1500.
107   uint32_t rtp = std::numeric_limits<uint32_t>::max() - 1500;
108   EXPECT_THAT(inter_frame_delay.CalculateDelay(rtp, clock.CurrentTime()),
109               Optional(TimeDelta::Zero()));
110 
111   // Rtp wraps around, now 1499.
112   rtp += kRtpTicksPerFrame;
113 
114   // Frame delay should be as normal, in this case simulated as 1ms late.
115   clock.AdvanceTime(kFrameDelay + TimeDelta::Millis(1));
116   EXPECT_THAT(inter_frame_delay.CalculateDelay(rtp, clock.CurrentTime()),
117               Optional(TimeDelta::Millis(1)));
118 }
119 
TEST(InterFrameDelayTest,MultipleWrapArounds)120 TEST(InterFrameDelayTest, MultipleWrapArounds) {
121   // Simulate a long pauses which cause wrap arounds multiple times.
122   constexpr Frequency k90Khz = Frequency::KiloHertz(90);
123   constexpr uint32_t kHalfRtp = std::numeric_limits<uint32_t>::max() / 2;
124   constexpr TimeDelta kWrapAroundDelay = kHalfRtp / k90Khz;
125 
126   InterFrameDelay inter_frame_delay;
127   // Use a fake clock to simplify time keeping.
128   SimulatedClock clock(kStartTime);
129   uint32_t rtp = 0;
130   EXPECT_THAT(inter_frame_delay.CalculateDelay(rtp, clock.CurrentTime()),
131               Optional(TimeDelta::Zero()));
132 
133   rtp += kHalfRtp;
134   clock.AdvanceTime(kWrapAroundDelay);
135   EXPECT_THAT(inter_frame_delay.CalculateDelay(rtp, clock.CurrentTime()),
136               Optional(TimeDelta::Zero()));
137   // 1st wrap around.
138   rtp += kHalfRtp + 1;
139   clock.AdvanceTime(kWrapAroundDelay + TimeDelta::Millis(1));
140   EXPECT_THAT(inter_frame_delay.CalculateDelay(rtp, clock.CurrentTime()),
141               Optional(TimeDelta::Millis(1) - (1 / k90Khz)));
142 
143   rtp += kHalfRtp;
144   clock.AdvanceTime(kWrapAroundDelay);
145   EXPECT_THAT(inter_frame_delay.CalculateDelay(rtp, clock.CurrentTime()),
146               Optional(TimeDelta::Zero()));
147   // 2nd wrap arounds.
148   rtp += kHalfRtp + 1;
149   clock.AdvanceTime(kWrapAroundDelay - TimeDelta::Millis(1));
150   EXPECT_THAT(inter_frame_delay.CalculateDelay(rtp, clock.CurrentTime()),
151               Optional(-TimeDelta::Millis(1) - (1 / k90Khz)));
152 
153   // Ensure short delay (large RTP delay) between wrap-arounds has correct
154   // jitter.
155   rtp += kHalfRtp;
156   clock.AdvanceTime(TimeDelta::Millis(10));
157   EXPECT_THAT(inter_frame_delay.CalculateDelay(rtp, clock.CurrentTime()),
158               Optional(-(kWrapAroundDelay - TimeDelta::Millis(10))));
159   // 3nd wrap arounds, this time with large RTP delay.
160   rtp += kHalfRtp + 1;
161   clock.AdvanceTime(TimeDelta::Millis(10));
162   EXPECT_THAT(
163       inter_frame_delay.CalculateDelay(rtp, clock.CurrentTime()),
164       Optional(-(kWrapAroundDelay - TimeDelta::Millis(10) + (1 / k90Khz))));
165 }
166 
TEST(InterFrameDelayTest,NegativeWrapAroundAfterPositiveWrapAround)167 TEST(InterFrameDelayTest, NegativeWrapAroundAfterPositiveWrapAround) {
168   InterFrameDelay inter_frame_delay;
169   // Use a fake clock to simplify time keeping.
170   SimulatedClock clock(kStartTime);
171   uint32_t rtp = std::numeric_limits<uint32_t>::max() - 1500;
172   EXPECT_THAT(inter_frame_delay.CalculateDelay(rtp, clock.CurrentTime()),
173               Optional(TimeDelta::Zero()));
174 
175   // Rtp wraps around, now 1499.
176   rtp += kRtpTicksPerFrame;
177   // Frame delay should be as normal, in this case simulated as 1ms late.
178   clock.AdvanceTime(kFrameDelay);
179   EXPECT_THAT(inter_frame_delay.CalculateDelay(rtp, clock.CurrentTime()),
180               Optional(TimeDelta::Zero()));
181 
182   // Wrap back.
183   rtp -= kRtpTicksPerFrame;
184   // Frame delay should be as normal, in this case simulated as 1ms late.
185   clock.AdvanceTime(kFrameDelay);
186   EXPECT_THAT(inter_frame_delay.CalculateDelay(rtp, clock.CurrentTime()),
187               Eq(absl::nullopt));
188 }
189 
190 }  // namespace webrtc
191