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