xref: /aosp_15_r20/external/webrtc/video/video_source_sink_controller_unittest.cc (revision d9f758449e529ab9291ac668be2861e7a55c2422)
1 /*
2  *  Copyright 2020 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 "video/video_source_sink_controller.h"
12 
13 #include <limits>
14 
15 #include "api/video/video_frame.h"
16 #include "api/video/video_source_interface.h"
17 #include "call/adaptation/video_source_restrictions.h"
18 #include "test/gmock.h"
19 #include "test/gtest.h"
20 
21 using testing::_;
22 
23 namespace webrtc {
24 
25 namespace {
26 
27 using FrameSize = rtc::VideoSinkWants::FrameSize;
28 constexpr int kIntUnconstrained = std::numeric_limits<int>::max();
29 
30 class MockVideoSinkWithVideoFrame : public rtc::VideoSinkInterface<VideoFrame> {
31  public:
~MockVideoSinkWithVideoFrame()32   ~MockVideoSinkWithVideoFrame() override {}
33 
34   MOCK_METHOD(void, OnFrame, (const VideoFrame& frame), (override));
35   MOCK_METHOD(void, OnDiscardedFrame, (), (override));
36 };
37 
38 class MockVideoSourceWithVideoFrame
39     : public rtc::VideoSourceInterface<VideoFrame> {
40  public:
~MockVideoSourceWithVideoFrame()41   ~MockVideoSourceWithVideoFrame() override {}
42 
43   MOCK_METHOD(void,
44               AddOrUpdateSink,
45               (rtc::VideoSinkInterface<VideoFrame>*,
46                const rtc::VideoSinkWants&),
47               (override));
48   MOCK_METHOD(void,
49               RemoveSink,
50               (rtc::VideoSinkInterface<VideoFrame>*),
51               (override));
52   MOCK_METHOD(void, RequestRefreshFrame, (), (override));
53 };
54 
55 }  // namespace
56 
TEST(VideoSourceSinkControllerTest,UnconstrainedByDefault)57 TEST(VideoSourceSinkControllerTest, UnconstrainedByDefault) {
58   MockVideoSinkWithVideoFrame sink;
59   MockVideoSourceWithVideoFrame source;
60   VideoSourceSinkController controller(&sink, &source);
61   EXPECT_EQ(controller.restrictions(), VideoSourceRestrictions());
62   EXPECT_FALSE(controller.pixels_per_frame_upper_limit().has_value());
63   EXPECT_FALSE(controller.frame_rate_upper_limit().has_value());
64   EXPECT_FALSE(controller.rotation_applied());
65   EXPECT_FALSE(controller.requested_resolution().has_value());
66   EXPECT_EQ(controller.resolution_alignment(), 1);
67 
68   EXPECT_CALL(source, AddOrUpdateSink(_, _))
69       .WillOnce([](rtc::VideoSinkInterface<VideoFrame>* sink,
70                    const rtc::VideoSinkWants& wants) {
71         EXPECT_FALSE(wants.rotation_applied);
72         EXPECT_EQ(wants.max_pixel_count, kIntUnconstrained);
73         EXPECT_EQ(wants.target_pixel_count, absl::nullopt);
74         EXPECT_EQ(wants.max_framerate_fps, kIntUnconstrained);
75         EXPECT_EQ(wants.resolution_alignment, 1);
76         EXPECT_FALSE(wants.requested_resolution.has_value());
77       });
78   controller.PushSourceSinkSettings();
79 }
80 
TEST(VideoSourceSinkControllerTest,VideoRestrictionsToSinkWants)81 TEST(VideoSourceSinkControllerTest, VideoRestrictionsToSinkWants) {
82   MockVideoSinkWithVideoFrame sink;
83   MockVideoSourceWithVideoFrame source;
84   VideoSourceSinkController controller(&sink, &source);
85 
86   VideoSourceRestrictions restrictions = controller.restrictions();
87   // max_pixels_per_frame() maps to `max_pixel_count`.
88   restrictions.set_max_pixels_per_frame(42u);
89   // target_pixels_per_frame() maps to `target_pixel_count`.
90   restrictions.set_target_pixels_per_frame(200u);
91   // max_frame_rate() maps to `max_framerate_fps`.
92   restrictions.set_max_frame_rate(30.0);
93   controller.SetRestrictions(restrictions);
94   EXPECT_CALL(source, AddOrUpdateSink(_, _))
95       .WillOnce([](rtc::VideoSinkInterface<VideoFrame>* sink,
96                    const rtc::VideoSinkWants& wants) {
97         EXPECT_EQ(wants.max_pixel_count, 42);
98         EXPECT_EQ(wants.target_pixel_count, 200);
99         EXPECT_EQ(wants.max_framerate_fps, 30);
100       });
101   controller.PushSourceSinkSettings();
102 
103   // pixels_per_frame_upper_limit() caps `max_pixel_count`.
104   controller.SetPixelsPerFrameUpperLimit(24);
105   // frame_rate_upper_limit() caps `max_framerate_fps`.
106   controller.SetFrameRateUpperLimit(10.0);
107 
108   EXPECT_CALL(source, AddOrUpdateSink(_, _))
109       .WillOnce([](rtc::VideoSinkInterface<VideoFrame>* sink,
110                    const rtc::VideoSinkWants& wants) {
111         EXPECT_EQ(wants.max_pixel_count, 24);
112         EXPECT_EQ(wants.max_framerate_fps, 10);
113       });
114   controller.PushSourceSinkSettings();
115 }
116 
TEST(VideoSourceSinkControllerTest,RotationApplied)117 TEST(VideoSourceSinkControllerTest, RotationApplied) {
118   MockVideoSinkWithVideoFrame sink;
119   MockVideoSourceWithVideoFrame source;
120   VideoSourceSinkController controller(&sink, &source);
121   controller.SetRotationApplied(true);
122   EXPECT_TRUE(controller.rotation_applied());
123 
124   EXPECT_CALL(source, AddOrUpdateSink(_, _))
125       .WillOnce([](rtc::VideoSinkInterface<VideoFrame>* sink,
126                    const rtc::VideoSinkWants& wants) {
127         EXPECT_TRUE(wants.rotation_applied);
128       });
129   controller.PushSourceSinkSettings();
130 }
131 
TEST(VideoSourceSinkControllerTest,ResolutionAlignment)132 TEST(VideoSourceSinkControllerTest, ResolutionAlignment) {
133   MockVideoSinkWithVideoFrame sink;
134   MockVideoSourceWithVideoFrame source;
135   VideoSourceSinkController controller(&sink, &source);
136   controller.SetResolutionAlignment(13);
137   EXPECT_EQ(controller.resolution_alignment(), 13);
138 
139   EXPECT_CALL(source, AddOrUpdateSink(_, _))
140       .WillOnce([](rtc::VideoSinkInterface<VideoFrame>* sink,
141                    const rtc::VideoSinkWants& wants) {
142         EXPECT_EQ(wants.resolution_alignment, 13);
143       });
144   controller.PushSourceSinkSettings();
145 }
146 
TEST(VideoSourceSinkControllerTest,PushSourceSinkSettingsWithoutSourceDoesNotCrash)147 TEST(VideoSourceSinkControllerTest,
148      PushSourceSinkSettingsWithoutSourceDoesNotCrash) {
149   MockVideoSinkWithVideoFrame sink;
150   VideoSourceSinkController controller(&sink, nullptr);
151   controller.PushSourceSinkSettings();
152 }
153 
TEST(VideoSourceSinkControllerTest,RequestsRefreshFrameWithSource)154 TEST(VideoSourceSinkControllerTest, RequestsRefreshFrameWithSource) {
155   MockVideoSinkWithVideoFrame sink;
156   MockVideoSourceWithVideoFrame source;
157   VideoSourceSinkController controller(&sink, &source);
158   EXPECT_CALL(source, RequestRefreshFrame);
159   controller.RequestRefreshFrame();
160 }
161 
TEST(VideoSourceSinkControllerTest,RequestsRefreshFrameWithoutSourceDoesNotCrash)162 TEST(VideoSourceSinkControllerTest,
163      RequestsRefreshFrameWithoutSourceDoesNotCrash) {
164   MockVideoSinkWithVideoFrame sink;
165   VideoSourceSinkController controller(&sink, nullptr);
166   controller.RequestRefreshFrame();
167 }
168 
TEST(VideoSourceSinkControllerTest,RequestedResolutionPropagatesToWants)169 TEST(VideoSourceSinkControllerTest, RequestedResolutionPropagatesToWants) {
170   MockVideoSinkWithVideoFrame sink;
171   MockVideoSourceWithVideoFrame source;
172   VideoSourceSinkController controller(&sink, &source);
173   controller.SetRequestedResolution(FrameSize(640, 360));
174   EXPECT_TRUE(controller.requested_resolution().has_value());
175 
176   EXPECT_CALL(source, AddOrUpdateSink(_, _))
177       .WillOnce([](rtc::VideoSinkInterface<VideoFrame>* sink,
178                    const rtc::VideoSinkWants& wants) {
179         EXPECT_EQ(*wants.requested_resolution, FrameSize(640, 360));
180       });
181   controller.PushSourceSinkSettings();
182 }
183 
TEST(VideoSourceSinkControllerTest,ActivePropagatesToWants)184 TEST(VideoSourceSinkControllerTest, ActivePropagatesToWants) {
185   MockVideoSinkWithVideoFrame sink;
186   MockVideoSourceWithVideoFrame source;
187   VideoSourceSinkController controller(&sink, &source);
188   controller.SetActive(true);
189   EXPECT_TRUE(controller.active());
190 
191   EXPECT_CALL(source, AddOrUpdateSink(_, _))
192       .WillOnce([](rtc::VideoSinkInterface<VideoFrame>* sink,
193                    const rtc::VideoSinkWants& wants) {
194         EXPECT_TRUE(wants.is_active);
195       });
196   controller.PushSourceSinkSettings();
197 }
198 
199 }  // namespace webrtc
200