xref: /aosp_15_r20/external/webrtc/video/frame_decode_timing_unittest.cc (revision d9f758449e529ab9291ac668be2861e7a55c2422)
1*d9f75844SAndroid Build Coastguard Worker /*
2*d9f75844SAndroid Build Coastguard Worker  *  Copyright (c) 2022 The WebRTC project authors. All Rights Reserved.
3*d9f75844SAndroid Build Coastguard Worker  *
4*d9f75844SAndroid Build Coastguard Worker  *  Use of this source code is governed by a BSD-style license
5*d9f75844SAndroid Build Coastguard Worker  *  that can be found in the LICENSE file in the root of the source
6*d9f75844SAndroid Build Coastguard Worker  *  tree. An additional intellectual property rights grant can be found
7*d9f75844SAndroid Build Coastguard Worker  *  in the file PATENTS.  All contributing project authors may
8*d9f75844SAndroid Build Coastguard Worker  *  be found in the AUTHORS file in the root of the source tree.
9*d9f75844SAndroid Build Coastguard Worker  */
10*d9f75844SAndroid Build Coastguard Worker 
11*d9f75844SAndroid Build Coastguard Worker #include "video/frame_decode_timing.h"
12*d9f75844SAndroid Build Coastguard Worker 
13*d9f75844SAndroid Build Coastguard Worker #include <stdint.h>
14*d9f75844SAndroid Build Coastguard Worker 
15*d9f75844SAndroid Build Coastguard Worker #include "absl/types/optional.h"
16*d9f75844SAndroid Build Coastguard Worker #include "api/units/time_delta.h"
17*d9f75844SAndroid Build Coastguard Worker #include "modules/video_coding/timing/timing.h"
18*d9f75844SAndroid Build Coastguard Worker #include "rtc_base/containers/flat_map.h"
19*d9f75844SAndroid Build Coastguard Worker #include "test/gmock.h"
20*d9f75844SAndroid Build Coastguard Worker #include "test/gtest.h"
21*d9f75844SAndroid Build Coastguard Worker #include "test/scoped_key_value_config.h"
22*d9f75844SAndroid Build Coastguard Worker #include "video/video_receive_stream2.h"
23*d9f75844SAndroid Build Coastguard Worker 
24*d9f75844SAndroid Build Coastguard Worker namespace webrtc {
25*d9f75844SAndroid Build Coastguard Worker 
26*d9f75844SAndroid Build Coastguard Worker using ::testing::AllOf;
27*d9f75844SAndroid Build Coastguard Worker using ::testing::Eq;
28*d9f75844SAndroid Build Coastguard Worker using ::testing::Field;
29*d9f75844SAndroid Build Coastguard Worker using ::testing::Optional;
30*d9f75844SAndroid Build Coastguard Worker 
31*d9f75844SAndroid Build Coastguard Worker namespace {
32*d9f75844SAndroid Build Coastguard Worker 
33*d9f75844SAndroid Build Coastguard Worker class FakeVCMTiming : public webrtc::VCMTiming {
34*d9f75844SAndroid Build Coastguard Worker  public:
FakeVCMTiming(Clock * clock,const FieldTrialsView & field_trials)35*d9f75844SAndroid Build Coastguard Worker   explicit FakeVCMTiming(Clock* clock, const FieldTrialsView& field_trials)
36*d9f75844SAndroid Build Coastguard Worker       : webrtc::VCMTiming(clock, field_trials) {}
37*d9f75844SAndroid Build Coastguard Worker 
RenderTime(uint32_t frame_timestamp,Timestamp now) const38*d9f75844SAndroid Build Coastguard Worker   Timestamp RenderTime(uint32_t frame_timestamp, Timestamp now) const override {
39*d9f75844SAndroid Build Coastguard Worker     RTC_DCHECK(render_time_map_.contains(frame_timestamp));
40*d9f75844SAndroid Build Coastguard Worker     auto it = render_time_map_.find(frame_timestamp);
41*d9f75844SAndroid Build Coastguard Worker     return it->second;
42*d9f75844SAndroid Build Coastguard Worker   }
43*d9f75844SAndroid Build Coastguard Worker 
MaxWaitingTime(Timestamp render_time,Timestamp now,bool too_many_frames_queued) const44*d9f75844SAndroid Build Coastguard Worker   TimeDelta MaxWaitingTime(Timestamp render_time,
45*d9f75844SAndroid Build Coastguard Worker                            Timestamp now,
46*d9f75844SAndroid Build Coastguard Worker                            bool too_many_frames_queued) const override {
47*d9f75844SAndroid Build Coastguard Worker     RTC_DCHECK(wait_time_map_.contains(render_time));
48*d9f75844SAndroid Build Coastguard Worker     auto it = wait_time_map_.find(render_time);
49*d9f75844SAndroid Build Coastguard Worker     return it->second;
50*d9f75844SAndroid Build Coastguard Worker   }
51*d9f75844SAndroid Build Coastguard Worker 
SetTimes(uint32_t frame_timestamp,Timestamp render_time,TimeDelta max_decode_wait)52*d9f75844SAndroid Build Coastguard Worker   void SetTimes(uint32_t frame_timestamp,
53*d9f75844SAndroid Build Coastguard Worker                 Timestamp render_time,
54*d9f75844SAndroid Build Coastguard Worker                 TimeDelta max_decode_wait) {
55*d9f75844SAndroid Build Coastguard Worker     render_time_map_.insert_or_assign(frame_timestamp, render_time);
56*d9f75844SAndroid Build Coastguard Worker     wait_time_map_.insert_or_assign(render_time, max_decode_wait);
57*d9f75844SAndroid Build Coastguard Worker   }
58*d9f75844SAndroid Build Coastguard Worker 
59*d9f75844SAndroid Build Coastguard Worker  protected:
60*d9f75844SAndroid Build Coastguard Worker   flat_map<uint32_t, Timestamp> render_time_map_;
61*d9f75844SAndroid Build Coastguard Worker   flat_map<Timestamp, TimeDelta> wait_time_map_;
62*d9f75844SAndroid Build Coastguard Worker };
63*d9f75844SAndroid Build Coastguard Worker }  // namespace
64*d9f75844SAndroid Build Coastguard Worker 
65*d9f75844SAndroid Build Coastguard Worker class FrameDecodeTimingTest : public ::testing::Test {
66*d9f75844SAndroid Build Coastguard Worker  public:
FrameDecodeTimingTest()67*d9f75844SAndroid Build Coastguard Worker   FrameDecodeTimingTest()
68*d9f75844SAndroid Build Coastguard Worker       : clock_(Timestamp::Millis(1000)),
69*d9f75844SAndroid Build Coastguard Worker         timing_(&clock_, field_trials_),
70*d9f75844SAndroid Build Coastguard Worker         frame_decode_scheduler_(&clock_, &timing_) {}
71*d9f75844SAndroid Build Coastguard Worker 
72*d9f75844SAndroid Build Coastguard Worker  protected:
73*d9f75844SAndroid Build Coastguard Worker   test::ScopedKeyValueConfig field_trials_;
74*d9f75844SAndroid Build Coastguard Worker   SimulatedClock clock_;
75*d9f75844SAndroid Build Coastguard Worker   FakeVCMTiming timing_;
76*d9f75844SAndroid Build Coastguard Worker   FrameDecodeTiming frame_decode_scheduler_;
77*d9f75844SAndroid Build Coastguard Worker };
78*d9f75844SAndroid Build Coastguard Worker 
TEST_F(FrameDecodeTimingTest,ReturnsWaitTimesWhenValid)79*d9f75844SAndroid Build Coastguard Worker TEST_F(FrameDecodeTimingTest, ReturnsWaitTimesWhenValid) {
80*d9f75844SAndroid Build Coastguard Worker   const TimeDelta decode_delay = TimeDelta::Millis(42);
81*d9f75844SAndroid Build Coastguard Worker   const Timestamp render_time = clock_.CurrentTime() + TimeDelta::Millis(60);
82*d9f75844SAndroid Build Coastguard Worker   timing_.SetTimes(90000, render_time, decode_delay);
83*d9f75844SAndroid Build Coastguard Worker 
84*d9f75844SAndroid Build Coastguard Worker   EXPECT_THAT(frame_decode_scheduler_.OnFrameBufferUpdated(
85*d9f75844SAndroid Build Coastguard Worker                   90000, 180000, kMaxWaitForFrame, false),
86*d9f75844SAndroid Build Coastguard Worker               Optional(AllOf(
87*d9f75844SAndroid Build Coastguard Worker                   Field(&FrameDecodeTiming::FrameSchedule::latest_decode_time,
88*d9f75844SAndroid Build Coastguard Worker                         Eq(clock_.CurrentTime() + decode_delay)),
89*d9f75844SAndroid Build Coastguard Worker                   Field(&FrameDecodeTiming::FrameSchedule::render_time,
90*d9f75844SAndroid Build Coastguard Worker                         Eq(render_time)))));
91*d9f75844SAndroid Build Coastguard Worker }
92*d9f75844SAndroid Build Coastguard Worker 
TEST_F(FrameDecodeTimingTest,FastForwardsFrameTooFarInThePast)93*d9f75844SAndroid Build Coastguard Worker TEST_F(FrameDecodeTimingTest, FastForwardsFrameTooFarInThePast) {
94*d9f75844SAndroid Build Coastguard Worker   const TimeDelta decode_delay =
95*d9f75844SAndroid Build Coastguard Worker       -FrameDecodeTiming::kMaxAllowedFrameDelay - TimeDelta::Millis(1);
96*d9f75844SAndroid Build Coastguard Worker   const Timestamp render_time = clock_.CurrentTime();
97*d9f75844SAndroid Build Coastguard Worker   timing_.SetTimes(90000, render_time, decode_delay);
98*d9f75844SAndroid Build Coastguard Worker 
99*d9f75844SAndroid Build Coastguard Worker   EXPECT_THAT(frame_decode_scheduler_.OnFrameBufferUpdated(
100*d9f75844SAndroid Build Coastguard Worker                   90000, 180000, kMaxWaitForFrame, false),
101*d9f75844SAndroid Build Coastguard Worker               Eq(absl::nullopt));
102*d9f75844SAndroid Build Coastguard Worker }
103*d9f75844SAndroid Build Coastguard Worker 
TEST_F(FrameDecodeTimingTest,NoFastForwardIfOnlyFrameToDecode)104*d9f75844SAndroid Build Coastguard Worker TEST_F(FrameDecodeTimingTest, NoFastForwardIfOnlyFrameToDecode) {
105*d9f75844SAndroid Build Coastguard Worker   const TimeDelta decode_delay =
106*d9f75844SAndroid Build Coastguard Worker       -FrameDecodeTiming::kMaxAllowedFrameDelay - TimeDelta::Millis(1);
107*d9f75844SAndroid Build Coastguard Worker   const Timestamp render_time = clock_.CurrentTime();
108*d9f75844SAndroid Build Coastguard Worker   timing_.SetTimes(90000, render_time, decode_delay);
109*d9f75844SAndroid Build Coastguard Worker 
110*d9f75844SAndroid Build Coastguard Worker   // Negative `decode_delay` means that `latest_decode_time` is now.
111*d9f75844SAndroid Build Coastguard Worker   EXPECT_THAT(frame_decode_scheduler_.OnFrameBufferUpdated(
112*d9f75844SAndroid Build Coastguard Worker                   90000, 90000, kMaxWaitForFrame, false),
113*d9f75844SAndroid Build Coastguard Worker               Optional(AllOf(
114*d9f75844SAndroid Build Coastguard Worker                   Field(&FrameDecodeTiming::FrameSchedule::latest_decode_time,
115*d9f75844SAndroid Build Coastguard Worker                         Eq(clock_.CurrentTime())),
116*d9f75844SAndroid Build Coastguard Worker                   Field(&FrameDecodeTiming::FrameSchedule::render_time,
117*d9f75844SAndroid Build Coastguard Worker                         Eq(render_time)))));
118*d9f75844SAndroid Build Coastguard Worker }
119*d9f75844SAndroid Build Coastguard Worker 
TEST_F(FrameDecodeTimingTest,MaxWaitCapped)120*d9f75844SAndroid Build Coastguard Worker TEST_F(FrameDecodeTimingTest, MaxWaitCapped) {
121*d9f75844SAndroid Build Coastguard Worker   TimeDelta frame_delay = TimeDelta::Millis(30);
122*d9f75844SAndroid Build Coastguard Worker   const TimeDelta decode_delay = TimeDelta::Seconds(3);
123*d9f75844SAndroid Build Coastguard Worker   const Timestamp render_time = clock_.CurrentTime() + TimeDelta::Seconds(3);
124*d9f75844SAndroid Build Coastguard Worker   timing_.SetTimes(90000, render_time, decode_delay);
125*d9f75844SAndroid Build Coastguard Worker   timing_.SetTimes(180000, render_time + frame_delay,
126*d9f75844SAndroid Build Coastguard Worker                    decode_delay + frame_delay);
127*d9f75844SAndroid Build Coastguard Worker 
128*d9f75844SAndroid Build Coastguard Worker   EXPECT_THAT(frame_decode_scheduler_.OnFrameBufferUpdated(
129*d9f75844SAndroid Build Coastguard Worker                   90000, 270000, kMaxWaitForFrame, false),
130*d9f75844SAndroid Build Coastguard Worker               Optional(AllOf(
131*d9f75844SAndroid Build Coastguard Worker                   Field(&FrameDecodeTiming::FrameSchedule::latest_decode_time,
132*d9f75844SAndroid Build Coastguard Worker                         Eq(clock_.CurrentTime() + kMaxWaitForFrame)),
133*d9f75844SAndroid Build Coastguard Worker                   Field(&FrameDecodeTiming::FrameSchedule::render_time,
134*d9f75844SAndroid Build Coastguard Worker                         Eq(render_time)))));
135*d9f75844SAndroid Build Coastguard Worker 
136*d9f75844SAndroid Build Coastguard Worker   // Test cap keyframe.
137*d9f75844SAndroid Build Coastguard Worker   clock_.AdvanceTime(frame_delay);
138*d9f75844SAndroid Build Coastguard Worker   EXPECT_THAT(frame_decode_scheduler_.OnFrameBufferUpdated(
139*d9f75844SAndroid Build Coastguard Worker                   180000, 270000, kMaxWaitForKeyFrame, false),
140*d9f75844SAndroid Build Coastguard Worker               Optional(AllOf(
141*d9f75844SAndroid Build Coastguard Worker                   Field(&FrameDecodeTiming::FrameSchedule::latest_decode_time,
142*d9f75844SAndroid Build Coastguard Worker                         Eq(clock_.CurrentTime() + kMaxWaitForKeyFrame)),
143*d9f75844SAndroid Build Coastguard Worker                   Field(&FrameDecodeTiming::FrameSchedule::render_time,
144*d9f75844SAndroid Build Coastguard Worker                         Eq(render_time + frame_delay)))));
145*d9f75844SAndroid Build Coastguard Worker }
146*d9f75844SAndroid Build Coastguard Worker 
147*d9f75844SAndroid Build Coastguard Worker }  // namespace webrtc
148